@kud/gh-ink 0.57.1 → 0.59.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/index.d.ts +126 -16
- package/dist/index.js +460 -166
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React2, { createContext, useState, useRef, useEffect, useMemo, useContext } from 'react';
|
|
2
2
|
import { useWindowSize, useInput, Text, Box } from 'ink';
|
|
3
|
-
import { colors, ScrollView, TextInput, useAppKeys, LoadingScreen,
|
|
3
|
+
import { colors, ScrollView, TextInput, useAppKeys, LoadingScreen, StatusMessage, FooterHints, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth, Pill } from '@kud/ink-ui';
|
|
4
4
|
import { isPassCheck, isFailCheck, isInconclusiveCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer } from '@kud/gh';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { $ } from 'zx';
|
|
@@ -634,15 +634,28 @@ var Progress = ({ row }) => {
|
|
|
634
634
|
/* @__PURE__ */ jsx(Text, { color: colors.secondary, children: GUTTER + fraction.padStart(FRACTION_COLS) })
|
|
635
635
|
] });
|
|
636
636
|
};
|
|
637
|
-
var
|
|
637
|
+
var railsOf = (rails) => rails === void 0 ? [] : Array.isArray(rails) ? rails : [rails];
|
|
638
|
+
var railRowsOf = (rails) => railsOf(rails).flatMap((s) => s.rows);
|
|
639
|
+
var linesFor = (rows) => HEADING_LINES + Math.max(1, rows) * ROW_LINES;
|
|
640
|
+
var railHeights = (height, rowCounts) => {
|
|
641
|
+
const out = [];
|
|
642
|
+
let remaining = height;
|
|
643
|
+
rowCounts.forEach((rows, i) => {
|
|
644
|
+
const share = Math.floor(remaining / (rowCounts.length - i));
|
|
645
|
+
const h = Math.min(share, linesFor(rows));
|
|
646
|
+
out.push(h);
|
|
647
|
+
remaining -= h;
|
|
648
|
+
});
|
|
649
|
+
return out;
|
|
650
|
+
};
|
|
651
|
+
var RailSection = ({
|
|
638
652
|
sidebar,
|
|
639
|
-
liveLabel
|
|
640
|
-
|
|
653
|
+
liveLabel,
|
|
654
|
+
content,
|
|
641
655
|
height,
|
|
642
|
-
focused
|
|
643
|
-
cursor
|
|
656
|
+
focused,
|
|
657
|
+
cursor
|
|
644
658
|
}) => {
|
|
645
|
-
const content = contentOf(width);
|
|
646
659
|
const labelCols = content - MARKS;
|
|
647
660
|
const liveCols = content - FACTS_FIXED;
|
|
648
661
|
const capacity = height === void 0 ? sidebar.rows.length : railCapacity(height, sidebar.rows.length);
|
|
@@ -653,6 +666,46 @@ var SidePanel = ({
|
|
|
653
666
|
const rule = "\u254C".repeat(
|
|
654
667
|
Math.max(0, content - [...sidebar.title].length - focus.length - 1)
|
|
655
668
|
);
|
|
669
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height, children: [
|
|
670
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
671
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: sidebar.title }),
|
|
672
|
+
focused ? /* @__PURE__ */ jsx(Text, { color: colors.accent, children: focus }) : null,
|
|
673
|
+
/* @__PURE__ */ jsx(Text, { color: colors.info, dimColor: true, children: ` ${rule}` })
|
|
674
|
+
] }),
|
|
675
|
+
sidebar.rows.length === 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft: MARKS, children: /* @__PURE__ */ jsx(Text, { color: colors.muted, children: "nothing open" }) }) : shown.map((row, i) => {
|
|
676
|
+
const active = focused && start + i === cursor;
|
|
677
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
678
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
679
|
+
/* @__PURE__ */ jsx(Text, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
680
|
+
/* @__PURE__ */ jsx(Text, { color: colors.accent, bold: true, children: row.wantsYou ? "\u2190 " : " " }),
|
|
681
|
+
/* @__PURE__ */ jsx(Text, { bold: active, children: truncateWords(row.label, labelCols) })
|
|
682
|
+
] }),
|
|
683
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
684
|
+
/* @__PURE__ */ jsx(Text, { color: row.markerColor, children: " ".repeat(FACTS_INDENT - 2) + (row.marker ?? " ") + " " }),
|
|
685
|
+
/* @__PURE__ */ jsx(Text, { color: colors.secondary, children: row.key.padEnd(KEY_COLS) + GUTTER }),
|
|
686
|
+
/* @__PURE__ */ jsx(Progress, { row }),
|
|
687
|
+
/* @__PURE__ */ jsx(Text, { children: GUTTER + (row.live !== void 0 ? liveLabel(row.live).slice(0, liveCols) : "") })
|
|
688
|
+
] })
|
|
689
|
+
] }, row.key);
|
|
690
|
+
}),
|
|
691
|
+
hidden > 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft: MARKS, children: /* @__PURE__ */ jsx(Text, { color: colors.muted, children: `+${hidden} more` }) }) : null
|
|
692
|
+
] });
|
|
693
|
+
};
|
|
694
|
+
var SidePanel = ({
|
|
695
|
+
sidebar,
|
|
696
|
+
liveLabel = defaultLiveLabel,
|
|
697
|
+
width = SIDEBAR_COLS,
|
|
698
|
+
height,
|
|
699
|
+
focused = false,
|
|
700
|
+
cursor = 0
|
|
701
|
+
}) => {
|
|
702
|
+
const content = contentOf(width);
|
|
703
|
+
const sections = railsOf(sidebar);
|
|
704
|
+
const heights = height === void 0 ? sections.map(() => void 0) : railHeights(
|
|
705
|
+
height,
|
|
706
|
+
sections.map((s) => s.rows.length)
|
|
707
|
+
);
|
|
708
|
+
let offset = 0;
|
|
656
709
|
return (
|
|
657
710
|
// A rule down the left rather than a full box: the rail's other three edges
|
|
658
711
|
// already have the frame's border a column or two away, and a second
|
|
@@ -660,7 +713,7 @@ var SidePanel = ({
|
|
|
660
713
|
// focus and act on, which this cannot be. One line is the whole claim: what
|
|
661
714
|
// is left of it is the list, what is right of it is not. In the frame's own
|
|
662
715
|
// colour and not dimmed, so the two rules read as one hierarchy.
|
|
663
|
-
/* @__PURE__ */
|
|
716
|
+
/* @__PURE__ */ jsx(
|
|
664
717
|
Box,
|
|
665
718
|
{
|
|
666
719
|
flexDirection: "column",
|
|
@@ -673,34 +726,113 @@ var SidePanel = ({
|
|
|
673
726
|
borderRight: false,
|
|
674
727
|
borderBottom: false,
|
|
675
728
|
paddingLeft: PAD,
|
|
676
|
-
children:
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
/* @__PURE__ */ jsx(Text, { children: GUTTER + (row.live !== void 0 ? liveLabel(row.live).slice(0, liveCols) : "") })
|
|
695
|
-
] })
|
|
696
|
-
] }, row.key);
|
|
697
|
-
}),
|
|
698
|
-
hidden > 0 ? /* @__PURE__ */ jsx(Box, { paddingLeft: MARKS, children: /* @__PURE__ */ jsx(Text, { color: colors.muted, children: `+${hidden} more` }) }) : null
|
|
699
|
-
]
|
|
729
|
+
children: sections.map((section, i) => {
|
|
730
|
+
const first = offset;
|
|
731
|
+
offset += section.rows.length;
|
|
732
|
+
const inside = focused && cursor >= first && cursor < offset;
|
|
733
|
+
const owns = inside || focused && sections.length === 1;
|
|
734
|
+
return /* @__PURE__ */ jsx(
|
|
735
|
+
RailSection,
|
|
736
|
+
{
|
|
737
|
+
sidebar: section,
|
|
738
|
+
liveLabel,
|
|
739
|
+
content,
|
|
740
|
+
height: heights[i],
|
|
741
|
+
focused: owns,
|
|
742
|
+
cursor: cursor - first
|
|
743
|
+
},
|
|
744
|
+
section.title
|
|
745
|
+
);
|
|
746
|
+
})
|
|
700
747
|
}
|
|
701
748
|
)
|
|
702
749
|
);
|
|
703
750
|
};
|
|
751
|
+
var stripGlyph = (state) => {
|
|
752
|
+
switch (state) {
|
|
753
|
+
case "ok":
|
|
754
|
+
return ["\u2713", colors.success];
|
|
755
|
+
case "warn":
|
|
756
|
+
return ["!", colors.warning];
|
|
757
|
+
case "fail":
|
|
758
|
+
return ["\u2717", colors.error];
|
|
759
|
+
case "unknown":
|
|
760
|
+
return ["\u25CB", colors.muted];
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
var ALARM = "\u25B2";
|
|
764
|
+
var SEVERITY = {
|
|
765
|
+
fail: 0,
|
|
766
|
+
warn: 1,
|
|
767
|
+
unknown: 2,
|
|
768
|
+
ok: 3
|
|
769
|
+
};
|
|
770
|
+
var ageLabel = (at, now = Date.now()) => {
|
|
771
|
+
if (at === void 0) return "";
|
|
772
|
+
const s = Math.max(0, Math.round((now - at) / 1e3));
|
|
773
|
+
if (s < 60) return `${s}s`;
|
|
774
|
+
const m = Math.round(s / 60);
|
|
775
|
+
if (m < 60) return `${m}m`;
|
|
776
|
+
return `${Math.round(m / 60)}h`;
|
|
777
|
+
};
|
|
778
|
+
var itemText = (item) => `${stripGlyph(item.state)[0]} ${item.key}${item.alarm ? ALARM : ""}`;
|
|
779
|
+
var stripLayout = (strip, width, now = Date.now()) => {
|
|
780
|
+
const age = ageLabel(strip.at, now);
|
|
781
|
+
const fixed = 2 + strip.title.length + 2 + (age ? age.length + 3 : 0);
|
|
782
|
+
const full = strip.items.map(itemText).join(" ");
|
|
783
|
+
if (fixed + full.length <= width)
|
|
784
|
+
return { parts: strip.items, summary: full, age };
|
|
785
|
+
const sorted = [...strip.items].sort(
|
|
786
|
+
(a, b) => SEVERITY[a.state] - SEVERITY[b.state]
|
|
787
|
+
);
|
|
788
|
+
const bad = sorted.filter((i) => i.state !== "ok" || i.alarm);
|
|
789
|
+
const ok = strip.items.length - bad.length;
|
|
790
|
+
const tally = (n, s) => n > 0 ? `${n} ${stripGlyph(s)[0]}` : "";
|
|
791
|
+
let named = [];
|
|
792
|
+
let text = "";
|
|
793
|
+
for (let n = bad.length; n >= 0; n--) {
|
|
794
|
+
named = bad.slice(0, n);
|
|
795
|
+
const rest = bad.slice(n);
|
|
796
|
+
const counts2 = ["fail", "warn", "unknown"].map((s) => tally(rest.filter((i) => i.state === s).length, s)).filter(Boolean);
|
|
797
|
+
text = [tally(ok, "ok"), ...counts2, ...named.map(itemText)].filter(Boolean).join(" \xB7 ");
|
|
798
|
+
if (fixed + text.length <= width) break;
|
|
799
|
+
}
|
|
800
|
+
return { parts: null, summary: text, age };
|
|
801
|
+
};
|
|
802
|
+
var StatusStripLine = ({
|
|
803
|
+
strip,
|
|
804
|
+
label = "status",
|
|
805
|
+
width,
|
|
806
|
+
now
|
|
807
|
+
}) => {
|
|
808
|
+
if (strip === void 0)
|
|
809
|
+
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
810
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
811
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${label} loading\u2026` })
|
|
812
|
+
] });
|
|
813
|
+
if (strip === null)
|
|
814
|
+
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
815
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u25CB " }),
|
|
816
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: `${label} no signal / not configured` })
|
|
817
|
+
] });
|
|
818
|
+
const { parts, summary, age } = stripLayout(strip, width, now);
|
|
819
|
+
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
820
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${strip.title} ` }),
|
|
821
|
+
parts ? parts.map((item, i) => {
|
|
822
|
+
const [glyph, color] = stripGlyph(item.state);
|
|
823
|
+
return /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
824
|
+
i > 0 ? /* @__PURE__ */ jsx(Text, { children: " " }) : null,
|
|
825
|
+
/* @__PURE__ */ jsx(Text, { color, bold: true, children: glyph }),
|
|
826
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
827
|
+
" ",
|
|
828
|
+
item.key
|
|
829
|
+
] }),
|
|
830
|
+
item.alarm ? /* @__PURE__ */ jsx(Text, { color: colors.error, bold: true, children: ALARM }) : null
|
|
831
|
+
] }, item.key);
|
|
832
|
+
}) : /* @__PURE__ */ jsx(Text, { children: summary }),
|
|
833
|
+
age ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${age}` }) : null
|
|
834
|
+
] });
|
|
835
|
+
};
|
|
704
836
|
var healthDisplay = {
|
|
705
837
|
none: { glyph: " ", color: colors.muted },
|
|
706
838
|
draft: { glyph: "~", color: colors.muted },
|
|
@@ -749,7 +881,7 @@ var displayFor = (h) => h ? healthDisplay[h] : UNREAD_DISPLAY;
|
|
|
749
881
|
|
|
750
882
|
// src/inbox/cache.ts
|
|
751
883
|
var cacheTtlMs = () => inboxConfig().cacheTtlMs;
|
|
752
|
-
var CACHE_VERSION =
|
|
884
|
+
var CACHE_VERSION = 5;
|
|
753
885
|
var cacheDir = () => join(
|
|
754
886
|
process.env.XDG_CACHE_HOME || join(homedir(), ".cache"),
|
|
755
887
|
inboxConfig().cacheNamespace
|
|
@@ -765,7 +897,7 @@ var readCache = (key) => {
|
|
|
765
897
|
login: raw.login ?? "",
|
|
766
898
|
at: raw.at ?? 0,
|
|
767
899
|
budget: raw.budget,
|
|
768
|
-
...Array.isArray(
|
|
900
|
+
...railsOf(raw.sidebar).every((s) => Array.isArray(s?.rows)) && raw.sidebar !== void 0 ? { sidebar: raw.sidebar } : {}
|
|
769
901
|
};
|
|
770
902
|
} catch {
|
|
771
903
|
return null;
|
|
@@ -1059,9 +1191,7 @@ var turnSentences = (item, login) => {
|
|
|
1059
1191
|
return [`${item.lastActor} spoke last (\u2190), ${when}. Your reply is owed.`];
|
|
1060
1192
|
const them = item.author && item.author !== login ? item.author : null;
|
|
1061
1193
|
if (!them)
|
|
1062
|
-
return [
|
|
1063
|
-
`You spoke last, ${when}. It is waiting on a reviewer, not on you.`
|
|
1064
|
-
];
|
|
1194
|
+
return [`You spoke last, ${when}. It is waiting on a reviewer, not on you.`];
|
|
1065
1195
|
const lines = [`You spoke last, ${when}. The ball is with ${them}.`];
|
|
1066
1196
|
if (d?.lastCommitAt && d.lastEventAt && d.lastCommitAt < d.lastEventAt)
|
|
1067
1197
|
lines.push(
|
|
@@ -1440,7 +1570,7 @@ var backdropStyle = (props) => ({
|
|
|
1440
1570
|
inverse: false,
|
|
1441
1571
|
backgroundColor: void 0
|
|
1442
1572
|
});
|
|
1443
|
-
var
|
|
1573
|
+
var Text4 = ({ children, ...props }) => {
|
|
1444
1574
|
const dimmed = useContext(DimContext);
|
|
1445
1575
|
return dimmed ? /* @__PURE__ */ jsx(Text, { ...props, ...backdropStyle(props), children }) : /* @__PURE__ */ jsx(Text, { ...props, children });
|
|
1446
1576
|
};
|
|
@@ -1521,6 +1651,11 @@ var unsubscribeFrom = async (item) => {
|
|
|
1521
1651
|
if (!id) throw new Error(`no node id for ${item.repo}#${item.number}`);
|
|
1522
1652
|
await quietly`gh api graphql -f query=${UNSUBSCRIBE_MUTATION} -f id=${id}`;
|
|
1523
1653
|
};
|
|
1654
|
+
var openInJira = (jiraBase, key, showFlash) => {
|
|
1655
|
+
quietly`open ${jiraBase}/${key}`.catch(() => {
|
|
1656
|
+
});
|
|
1657
|
+
showFlash(`\u2197 Opened ${key} in Jira`);
|
|
1658
|
+
};
|
|
1524
1659
|
var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions, onRefresh, onRemove, onOpenView, ext) => {
|
|
1525
1660
|
if (item.kind === "repo-header" || item.kind === "subgroup-header" || item.kind === "show-more" || item.kind === "show-less")
|
|
1526
1661
|
return [];
|
|
@@ -1728,11 +1863,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
1728
1863
|
actions.push({
|
|
1729
1864
|
label: `Open ${jiraKey} in Jira`,
|
|
1730
1865
|
hint: "t",
|
|
1731
|
-
run: () =>
|
|
1732
|
-
quietly`open ${jiraBase}/${jiraKey}`.catch(() => {
|
|
1733
|
-
});
|
|
1734
|
-
showFlash(`\u2197 Opened ${jiraKey} in Jira`);
|
|
1735
|
-
}
|
|
1866
|
+
run: () => openInJira(jiraBase, jiraKey, showFlash)
|
|
1736
1867
|
});
|
|
1737
1868
|
}
|
|
1738
1869
|
}
|
|
@@ -1835,13 +1966,13 @@ var InboxHeader = ({
|
|
|
1835
1966
|
COLS - brand.length - countSeg.length - userSeg.length - workLabel.length - budgetSeg.length - statusSeg.length
|
|
1836
1967
|
);
|
|
1837
1968
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1838
|
-
/* @__PURE__ */ jsx(
|
|
1839
|
-
/* @__PURE__ */ jsx(
|
|
1840
|
-
userSeg ? /* @__PURE__ */ jsx(
|
|
1841
|
-
scopeLabel ? /* @__PURE__ */ jsx(
|
|
1842
|
-
budgetLabel ? /* @__PURE__ */ jsx(
|
|
1969
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, bold: true, children: brand }),
|
|
1970
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: countSeg }),
|
|
1971
|
+
userSeg ? /* @__PURE__ */ jsx(Text4, { children: userSeg }) : null,
|
|
1972
|
+
scopeLabel ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: workLabel }) : null,
|
|
1973
|
+
budgetLabel ? /* @__PURE__ */ jsx(Text4, { bold: true, color: budgetCritical ? "#FF5F5F" : colors.accent, children: budgetSeg }) : null,
|
|
1843
1974
|
statusText ? /* @__PURE__ */ jsx(
|
|
1844
|
-
|
|
1975
|
+
Text4,
|
|
1845
1976
|
{
|
|
1846
1977
|
color: statusColor,
|
|
1847
1978
|
dimColor: !statusColor,
|
|
@@ -1849,9 +1980,10 @@ var InboxHeader = ({
|
|
|
1849
1980
|
children: statusSeg
|
|
1850
1981
|
}
|
|
1851
1982
|
) : null,
|
|
1852
|
-
/* @__PURE__ */ jsx(
|
|
1983
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, dimColor: true, children: "\u254C".repeat(fill) })
|
|
1853
1984
|
] });
|
|
1854
1985
|
};
|
|
1986
|
+
var stripSignature = (strip) => strip === null ? "\u2205" : strip.items.map((i) => `${i.key}=${i.state}${i.alarm ? "\u25B2" : ""}`).join(",");
|
|
1855
1987
|
var toCiStatusState = (status) => status ? { kind: "ready", status } : { kind: "error" };
|
|
1856
1988
|
var sameCiStatusState = (a, b) => {
|
|
1857
1989
|
if (a.kind !== b.kind) return false;
|
|
@@ -1872,24 +2004,24 @@ var CiStatusLine = ({
|
|
|
1872
2004
|
const name = job ?? "ci";
|
|
1873
2005
|
if (state.kind === "loading")
|
|
1874
2006
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1875
|
-
/* @__PURE__ */ jsx(
|
|
1876
|
-
/* @__PURE__ */ jsx(
|
|
2007
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " \xB7 " }),
|
|
2008
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: `${name} loading\u2026` })
|
|
1877
2009
|
] });
|
|
1878
2010
|
if (state.kind === "error")
|
|
1879
2011
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1880
|
-
/* @__PURE__ */ jsx(
|
|
1881
|
-
/* @__PURE__ */ jsx(
|
|
2012
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.error, bold: true, children: " \u2717 " }),
|
|
2013
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: `${name} no build / not configured` })
|
|
1882
2014
|
] });
|
|
1883
2015
|
const { status } = state;
|
|
1884
2016
|
const [, color] = jenkinsResultDisplay(status.result, status.building);
|
|
1885
2017
|
const label = status.building ? "BUILDING" : status.result;
|
|
1886
2018
|
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1887
|
-
/* @__PURE__ */ jsx(
|
|
1888
|
-
/* @__PURE__ */ jsx(
|
|
1889
|
-
/* @__PURE__ */ jsx(
|
|
1890
|
-
/* @__PURE__ */ jsx(
|
|
1891
|
-
/* @__PURE__ */ jsx(
|
|
1892
|
-
status.age ? /* @__PURE__ */ jsx(
|
|
2019
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " " }),
|
|
2020
|
+
/* @__PURE__ */ jsx(Text4, { color, bold: true, children: "\u25CF " }),
|
|
2021
|
+
/* @__PURE__ */ jsx(Text4, { bold: true, children: status.job }),
|
|
2022
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " " + label }),
|
|
2023
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, children: " #" + status.buildNumber }),
|
|
2024
|
+
status.age ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: " " + status.age }) : null
|
|
1893
2025
|
] });
|
|
1894
2026
|
};
|
|
1895
2027
|
var FENCE_COLS = 46;
|
|
@@ -1902,10 +2034,10 @@ var RepoHeaderRow = ({
|
|
|
1902
2034
|
const fill = Math.max(4, FENCE_COLS - label.length);
|
|
1903
2035
|
const rule = "\u2500".repeat(fill);
|
|
1904
2036
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
1905
|
-
/* @__PURE__ */ jsx(
|
|
1906
|
-
/* @__PURE__ */ jsx(
|
|
2037
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2038
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: !active, children: "\u2500\u2500 " }),
|
|
1907
2039
|
/* @__PURE__ */ jsx(
|
|
1908
|
-
|
|
2040
|
+
Text4,
|
|
1909
2041
|
{
|
|
1910
2042
|
dimColor: false,
|
|
1911
2043
|
color: active ? void 0 : colors.secondary,
|
|
@@ -1913,7 +2045,7 @@ var RepoHeaderRow = ({
|
|
|
1913
2045
|
children: repo
|
|
1914
2046
|
}
|
|
1915
2047
|
),
|
|
1916
|
-
/* @__PURE__ */ jsx(
|
|
2048
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: !active, children: " " + rule })
|
|
1917
2049
|
] });
|
|
1918
2050
|
};
|
|
1919
2051
|
var MERGED_HOLD_MS = 3e3;
|
|
@@ -1978,22 +2110,22 @@ var ItemRow = ({
|
|
|
1978
2110
|
return /* @__PURE__ */ jsx(RepoHeaderRow, { repo: item.repo, gap: gap ?? false, active });
|
|
1979
2111
|
if (item.kind === "subgroup-header")
|
|
1980
2112
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
1981
|
-
/* @__PURE__ */ jsx(
|
|
1982
|
-
/* @__PURE__ */ jsx(
|
|
2113
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, bold: true, children: " \xBB " }),
|
|
2114
|
+
/* @__PURE__ */ jsx(Text4, { bold: true, children: item.label })
|
|
1983
2115
|
] });
|
|
1984
2116
|
if (item.kind === "show-more")
|
|
1985
2117
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1986
|
-
/* @__PURE__ */ jsx(
|
|
1987
|
-
/* @__PURE__ */ jsx(
|
|
1988
|
-
/* @__PURE__ */ jsx(
|
|
1989
|
-
/* @__PURE__ */ jsx(
|
|
2118
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2119
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: prefix }),
|
|
2120
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
2121
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: `+${item.hidden.length} more` })
|
|
1990
2122
|
] });
|
|
1991
2123
|
if (item.kind === "show-less")
|
|
1992
2124
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
1993
|
-
/* @__PURE__ */ jsx(
|
|
1994
|
-
/* @__PURE__ */ jsx(
|
|
1995
|
-
/* @__PURE__ */ jsx(
|
|
1996
|
-
/* @__PURE__ */ jsx(
|
|
2125
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2126
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: prefix }),
|
|
2127
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: active ? "\u21B5 " : " " }),
|
|
2128
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "show less" })
|
|
1997
2129
|
] });
|
|
1998
2130
|
if (item.kind === "task") {
|
|
1999
2131
|
const note = item.note ?? "";
|
|
@@ -2003,14 +2135,14 @@ var ItemRow = ({
|
|
|
2003
2135
|
cols - item.key.length - note.length - (item.pill ? pillWidth(item.pill) + 1 : 0) - (farewellLabel ? pillWidth(farewellLabel) + 2 : 0) - prefix.length - (markerCols > 0 ? markerCols + 1 : 0) - 12
|
|
2004
2136
|
);
|
|
2005
2137
|
return /* @__PURE__ */ jsxs(Box, { marginTop: gap ? 1 : 0, children: [
|
|
2006
|
-
/* @__PURE__ */ jsx(
|
|
2007
|
-
/* @__PURE__ */ jsx(
|
|
2008
|
-
/* @__PURE__ */ jsx(
|
|
2009
|
-
/* @__PURE__ */ jsx(
|
|
2010
|
-
markerCols > 0 ? /* @__PURE__ */ jsx(
|
|
2011
|
-
/* @__PURE__ */ jsx(
|
|
2138
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2139
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: prefix }),
|
|
2140
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: parent ? "\u252C " : " " }),
|
|
2141
|
+
/* @__PURE__ */ jsx(Text4, { bold: true, color: transient ? TRANSIT_COLOUR[transient] : void 0, children: transitIcon + " " }),
|
|
2142
|
+
markerCols > 0 ? /* @__PURE__ */ jsx(Text4, { color: item.markerColor, children: (item.marker ?? "").padEnd(markerCols) + " " }) : null,
|
|
2143
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, bold: active, children: item.key + " " }),
|
|
2012
2144
|
/* @__PURE__ */ jsx(
|
|
2013
|
-
|
|
2145
|
+
Text4,
|
|
2014
2146
|
{
|
|
2015
2147
|
bold: active || !!transient && isArrival(transient),
|
|
2016
2148
|
dimColor: !!transient && isDeparture(transient),
|
|
@@ -2019,7 +2151,7 @@ var ItemRow = ({
|
|
|
2019
2151
|
}
|
|
2020
2152
|
),
|
|
2021
2153
|
item.pill && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2022
|
-
/* @__PURE__ */ jsx(
|
|
2154
|
+
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2023
2155
|
/* @__PURE__ */ jsx(
|
|
2024
2156
|
Pill,
|
|
2025
2157
|
{
|
|
@@ -2030,9 +2162,9 @@ var ItemRow = ({
|
|
|
2030
2162
|
}
|
|
2031
2163
|
)
|
|
2032
2164
|
] }) : null,
|
|
2033
|
-
note ? /* @__PURE__ */ jsx(
|
|
2165
|
+
note ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` ${note}` }) : null,
|
|
2034
2166
|
farewellLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2035
|
-
/* @__PURE__ */ jsx(
|
|
2167
|
+
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2036
2168
|
/* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR.out, children: farewellLabel })
|
|
2037
2169
|
] }) : null
|
|
2038
2170
|
] });
|
|
@@ -2048,7 +2180,7 @@ var ItemRow = ({
|
|
|
2048
2180
|
const sizeParts = sizePartsOf(item);
|
|
2049
2181
|
const unresolvedLabel = item.unresolved > 0 ? `\uF086 ${item.unresolved}` : "";
|
|
2050
2182
|
const agePair = item.activityAge && item.activityAge !== item.age ? { activity: item.activityAge, lifetime: item.age } : null;
|
|
2051
|
-
const
|
|
2183
|
+
const ageLabel2 = agePair ? `${agePair.activity} (${agePair.lifetime})` : item.age;
|
|
2052
2184
|
const mergedLabel = merged ? "merged" : "";
|
|
2053
2185
|
const pillCaps = [mergedLabel, farewellLabel].filter(Boolean).length * 2;
|
|
2054
2186
|
const repoLabel = depthOf(item) > 0 ? item.repo : "";
|
|
@@ -2081,7 +2213,7 @@ var ItemRow = ({
|
|
|
2081
2213
|
};
|
|
2082
2214
|
const widthOf2 = () => {
|
|
2083
2215
|
const suffix = [
|
|
2084
|
-
givingUp.age ? "" :
|
|
2216
|
+
givingUp.age ? "" : ageLabel2 || "",
|
|
2085
2217
|
// ASCII only, so no PUA double-width correction — see the label cell.
|
|
2086
2218
|
givingUp.size ? "" : sizeLabel || "",
|
|
2087
2219
|
givingUp.threads ? "" : unresolvedLabel,
|
|
@@ -2107,13 +2239,13 @@ var ItemRow = ({
|
|
|
2107
2239
|
const labelLabel = labelCell();
|
|
2108
2240
|
const titleMax = Math.max(1, cols - widthOf2());
|
|
2109
2241
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2110
|
-
/* @__PURE__ */ jsx(
|
|
2111
|
-
/* @__PURE__ */ jsx(
|
|
2112
|
-
/* @__PURE__ */ jsx(
|
|
2113
|
-
/* @__PURE__ */ jsx(
|
|
2114
|
-
/* @__PURE__ */ jsx(
|
|
2242
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2243
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: prefix }),
|
|
2244
|
+
/* @__PURE__ */ jsx(Text4, { color, bold: true, children: icon + " " }),
|
|
2245
|
+
/* @__PURE__ */ jsx(Text4, { color: turnColor, bold: turnIcon === "\u2190", children: turnIcon + " " }),
|
|
2246
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, children: numStr }),
|
|
2115
2247
|
/* @__PURE__ */ jsx(
|
|
2116
|
-
|
|
2248
|
+
Text4,
|
|
2117
2249
|
{
|
|
2118
2250
|
bold: active || !!transient && isArrival(transient),
|
|
2119
2251
|
dimColor: !!transient && isDeparture(transient),
|
|
@@ -2121,33 +2253,33 @@ var ItemRow = ({
|
|
|
2121
2253
|
children: truncate(item.title, titleMax) + " "
|
|
2122
2254
|
}
|
|
2123
2255
|
),
|
|
2124
|
-
labelLabel ? /* @__PURE__ */ jsx(
|
|
2125
|
-
repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(
|
|
2126
|
-
sizeParts && !givingUp.size ? /* @__PURE__ */ jsxs(
|
|
2256
|
+
labelLabel ? /* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: labelLabel + " " }) : null,
|
|
2257
|
+
repoLabel && !givingUp.repo ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: repoLabel }) : null,
|
|
2258
|
+
sizeParts && !givingUp.size ? /* @__PURE__ */ jsxs(Text4, { children: [
|
|
2127
2259
|
" ",
|
|
2128
|
-
/* @__PURE__ */ jsx(
|
|
2260
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.success, children: sizeParts.added }),
|
|
2129
2261
|
" ",
|
|
2130
|
-
/* @__PURE__ */ jsx(
|
|
2262
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.error, children: sizeParts.removed })
|
|
2131
2263
|
] }) : null,
|
|
2132
2264
|
unresolvedLabel && !givingUp.threads ? /* @__PURE__ */ jsx(
|
|
2133
|
-
|
|
2265
|
+
Text4,
|
|
2134
2266
|
{
|
|
2135
2267
|
bold: !spokeLast,
|
|
2136
2268
|
color: spokeLast ? colors.secondary : colors.accent,
|
|
2137
2269
|
children: " " + unresolvedLabel
|
|
2138
2270
|
}
|
|
2139
2271
|
) : null,
|
|
2140
|
-
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(
|
|
2141
|
-
|
|
2142
|
-
/* @__PURE__ */ jsx(
|
|
2143
|
-
/* @__PURE__ */ jsx(
|
|
2144
|
-
] }) : /* @__PURE__ */ jsx(
|
|
2272
|
+
showAuthor && !givingUp.author ? /* @__PURE__ */ jsx(Text4, { dimColor: true, italic: true, children: " by " + item.author }) : null,
|
|
2273
|
+
ageLabel2 && !givingUp.age ? agePair ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2274
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: " " + agePair.activity }),
|
|
2275
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` (${agePair.lifetime})` })
|
|
2276
|
+
] }) : /* @__PURE__ */ jsx(Text4, { color: colors.secondary, children: " " + ageLabel2 }) : null,
|
|
2145
2277
|
mergedLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2146
|
-
/* @__PURE__ */ jsx(
|
|
2278
|
+
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2147
2279
|
/* @__PURE__ */ jsx(Pill, { color: MERGED_COLOUR, children: mergedLabel })
|
|
2148
2280
|
] }) : null,
|
|
2149
2281
|
farewellLabel && !backdropped ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2150
|
-
/* @__PURE__ */ jsx(
|
|
2282
|
+
/* @__PURE__ */ jsx(Text4, { children: " " }),
|
|
2151
2283
|
/* @__PURE__ */ jsx(Pill, { color: TRANSIT_COLOUR.out, children: farewellLabel })
|
|
2152
2284
|
] }) : null
|
|
2153
2285
|
] });
|
|
@@ -2195,15 +2327,15 @@ var ActionMenu = ({
|
|
|
2195
2327
|
paddingX: 1,
|
|
2196
2328
|
marginTop: 1,
|
|
2197
2329
|
children: [
|
|
2198
|
-
/* @__PURE__ */ jsx(
|
|
2199
|
-
/* @__PURE__ */ jsx(
|
|
2330
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, bold: true, children: title }),
|
|
2331
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
2200
2332
|
actions.map((a, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
2201
|
-
/* @__PURE__ */ jsx(
|
|
2202
|
-
/* @__PURE__ */ jsx(
|
|
2203
|
-
/* @__PURE__ */ jsx(
|
|
2333
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: i === cursor ? "\u276F " : " " }),
|
|
2334
|
+
/* @__PURE__ */ jsx(Text4, { bold: i === cursor, children: a.label }),
|
|
2335
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " " + a.hint })
|
|
2204
2336
|
] }, a.label)),
|
|
2205
|
-
/* @__PURE__ */ jsx(
|
|
2206
|
-
/* @__PURE__ */ jsx(
|
|
2337
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "\u2500".repeat(32) }),
|
|
2338
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "\u2191\u2193 navigate \u21B5 confirm esc cancel" })
|
|
2207
2339
|
]
|
|
2208
2340
|
}
|
|
2209
2341
|
);
|
|
@@ -2251,11 +2383,11 @@ var LegendGroup = ({
|
|
|
2251
2383
|
width,
|
|
2252
2384
|
marginRight
|
|
2253
2385
|
}) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width, marginRight, children: [
|
|
2254
|
-
pinned !== void 0 ? /* @__PURE__ */ jsx(
|
|
2386
|
+
pinned !== void 0 ? /* @__PURE__ */ jsx(Text4, { bold: true, dimColor: true, children: pinned ?? " " }) : null,
|
|
2255
2387
|
lines.map(
|
|
2256
|
-
(line, index) => line.kind === "gap" ? /* @__PURE__ */ jsx(
|
|
2257
|
-
/* @__PURE__ */ jsx(
|
|
2258
|
-
/* @__PURE__ */ jsx(
|
|
2388
|
+
(line, index) => line.kind === "gap" ? /* @__PURE__ */ jsx(Text4, { children: " " }, index) : line.kind === "title" ? /* @__PURE__ */ jsx(Text4, { bold: true, dimColor: true, children: line.text }, index) : /* @__PURE__ */ jsxs(Box, { children: [
|
|
2389
|
+
/* @__PURE__ */ jsx(Text4, { color: line.row.color, bold: line.row.bold, children: line.row.cell.padEnd(line.cellWidth) }),
|
|
2390
|
+
/* @__PURE__ */ jsx(Text4, { wrap: "truncate-end", children: line.row.label })
|
|
2259
2391
|
] }, index)
|
|
2260
2392
|
)
|
|
2261
2393
|
] });
|
|
@@ -2289,7 +2421,10 @@ var HelpModal = ({
|
|
|
2289
2421
|
["p", "open repo in new pane"],
|
|
2290
2422
|
["u", "unsubscribe from this item"],
|
|
2291
2423
|
["x", "remove yourself as reviewer"],
|
|
2292
|
-
...hasJira ? [
|
|
2424
|
+
...hasJira ? [
|
|
2425
|
+
["t", "Jira: move / open ticket"],
|
|
2426
|
+
["\u2303K", "launch \xB7 jump to a ticket by key"]
|
|
2427
|
+
] : [],
|
|
2293
2428
|
["/", "search"],
|
|
2294
2429
|
["f", "filter by repo"],
|
|
2295
2430
|
["r", "refresh"],
|
|
@@ -2373,8 +2508,8 @@ var HelpModal = ({
|
|
|
2373
2508
|
width: contentWidth + MODAL_CHROME_COLS,
|
|
2374
2509
|
children: [
|
|
2375
2510
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2376
|
-
/* @__PURE__ */ jsx(
|
|
2377
|
-
scrollable ? /* @__PURE__ */ jsx(
|
|
2511
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, bold: true, children: "Legend" }),
|
|
2512
|
+
scrollable ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` ${offset + 1}\u2013${offset + shown} of ${totalRows}` }) : null
|
|
2378
2513
|
] }),
|
|
2379
2514
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, width: contentWidth, children: groups.map((group, index) => /* @__PURE__ */ jsx(
|
|
2380
2515
|
LegendGroup,
|
|
@@ -2386,8 +2521,8 @@ var HelpModal = ({
|
|
|
2386
2521
|
},
|
|
2387
2522
|
group[0]?.title ?? index
|
|
2388
2523
|
)) }),
|
|
2389
|
-
tabHelp && !scrollable ? /* @__PURE__ */ jsx(
|
|
2390
|
-
/* @__PURE__ */ jsx(
|
|
2524
|
+
tabHelp && !scrollable ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: LEGEND_FOOTNOTE }) : null,
|
|
2525
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: scrollable ? "\u2191\u2193 scroll \xB7 esc \xB7 ? close" : "esc \xB7 ? close" })
|
|
2391
2526
|
]
|
|
2392
2527
|
}
|
|
2393
2528
|
);
|
|
@@ -2402,13 +2537,13 @@ var ExplainModal = ({ item, login }) => /* @__PURE__ */ jsxs(
|
|
|
2402
2537
|
paddingX: 1,
|
|
2403
2538
|
width: Math.min(COLS, 78),
|
|
2404
2539
|
children: [
|
|
2405
|
-
/* @__PURE__ */ jsx(
|
|
2406
|
-
/* @__PURE__ */ jsx(
|
|
2540
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, bold: true, children: `#${item.number} \xB7 ${item.repo}` }),
|
|
2541
|
+
/* @__PURE__ */ jsx(Text4, { children: item.title }),
|
|
2407
2542
|
explainItem(item, login).map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
2408
|
-
/* @__PURE__ */ jsx(
|
|
2409
|
-
section.lines.map((line, i) => /* @__PURE__ */ jsx(
|
|
2543
|
+
/* @__PURE__ */ jsx(Text4, { bold: true, dimColor: true, children: section.heading }),
|
|
2544
|
+
section.lines.map((line, i) => /* @__PURE__ */ jsx(Text4, { children: " " + line }, i))
|
|
2410
2545
|
] }, section.heading)),
|
|
2411
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
2546
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text4, { dimColor: true, children: "esc \xB7 e close" }) })
|
|
2412
2547
|
]
|
|
2413
2548
|
}
|
|
2414
2549
|
);
|
|
@@ -2434,21 +2569,21 @@ var RepoPicker = ({
|
|
|
2434
2569
|
paddingX: 1,
|
|
2435
2570
|
minWidth: 42,
|
|
2436
2571
|
children: [
|
|
2437
|
-
/* @__PURE__ */ jsx(
|
|
2438
|
-
/* @__PURE__ */ jsx(
|
|
2572
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, bold: true, children: `Filter by repo (${selected.size} on)` }),
|
|
2573
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
2439
2574
|
visible.map((repo, i) => {
|
|
2440
2575
|
const idx = start + i;
|
|
2441
2576
|
const on = selected.has(repo);
|
|
2442
2577
|
const active = idx === cursor;
|
|
2443
2578
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
2444
|
-
/* @__PURE__ */ jsx(
|
|
2445
|
-
/* @__PURE__ */ jsx(
|
|
2446
|
-
/* @__PURE__ */ jsx(
|
|
2579
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: active ? "\u276F " : " " }),
|
|
2580
|
+
/* @__PURE__ */ jsx(Text4, { color: on ? "green" : void 0, children: on ? "\u25C9 " : "\u25CB " }),
|
|
2581
|
+
/* @__PURE__ */ jsx(Text4, { bold: active, children: repo })
|
|
2447
2582
|
] }, repo);
|
|
2448
2583
|
}),
|
|
2449
|
-
repos.length > budget ? /* @__PURE__ */ jsx(
|
|
2450
|
-
/* @__PURE__ */ jsx(
|
|
2451
|
-
/* @__PURE__ */ jsx(
|
|
2584
|
+
repos.length > budget ? /* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` \u2026 ${repos.length} repos total` }) : null,
|
|
2585
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "\u2500".repeat(36) }),
|
|
2586
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: "space toggle \xB7 a clear all \xB7 \u21B5/esc done" })
|
|
2452
2587
|
]
|
|
2453
2588
|
}
|
|
2454
2589
|
);
|
|
@@ -2464,6 +2599,7 @@ var BrowseScreen = ({
|
|
|
2464
2599
|
login,
|
|
2465
2600
|
jiraBase,
|
|
2466
2601
|
jiraKeyRe,
|
|
2602
|
+
jiraSetupHint,
|
|
2467
2603
|
jiraTransitions,
|
|
2468
2604
|
onRefresh,
|
|
2469
2605
|
onActed,
|
|
@@ -2482,6 +2618,8 @@ var BrowseScreen = ({
|
|
|
2482
2618
|
extensions,
|
|
2483
2619
|
ciStatusState,
|
|
2484
2620
|
ciJob,
|
|
2621
|
+
stripState,
|
|
2622
|
+
stripLabel,
|
|
2485
2623
|
tabHelp,
|
|
2486
2624
|
origin,
|
|
2487
2625
|
budget,
|
|
@@ -2520,14 +2658,16 @@ var BrowseScreen = ({
|
|
|
2520
2658
|
const [helpScroll, setHelpScroll] = useState(0);
|
|
2521
2659
|
const [helpRange, setHelpRange] = useState({ max: 0, page: 1 });
|
|
2522
2660
|
const [explain, setExplain] = useState(false);
|
|
2661
|
+
const [palette, setPalette] = useState(null);
|
|
2523
2662
|
const filterActive = search != null || repoFilter.size > 0;
|
|
2524
2663
|
const reserveCiRow = ciStatusState != null;
|
|
2664
|
+
const reserveStripRow = stripState != null;
|
|
2525
2665
|
const ciStatus = ciStatusState?.kind === "ready" ? ciStatusState.status : null;
|
|
2526
2666
|
const listHeight = Math.max(
|
|
2527
2667
|
5,
|
|
2528
2668
|
// -10 rather than -8: the extra 2 are the frame's top and bottom border
|
|
2529
2669
|
// rows, so the tree never grows taller than the terminal inside the frame.
|
|
2530
|
-
rows - 10 - (filterActive ? 2 : 0) - (reserveCiRow ? 2 : 0)
|
|
2670
|
+
rows - 10 - (filterActive ? 2 : 0) - (reserveCiRow ? 2 : 0) - (reserveStripRow ? 2 : 0)
|
|
2531
2671
|
);
|
|
2532
2672
|
useEffect(() => {
|
|
2533
2673
|
setCursors((p) => ({ ...p, [activeId]: 0 }));
|
|
@@ -2621,13 +2761,17 @@ var BrowseScreen = ({
|
|
|
2621
2761
|
return out;
|
|
2622
2762
|
}, [localSections, transients]);
|
|
2623
2763
|
const [railOpen, setRailOpen] = useState(false);
|
|
2624
|
-
const
|
|
2764
|
+
const rails = railsOf(sidebar);
|
|
2765
|
+
const hasRail = rails.length > 0;
|
|
2766
|
+
const railTitle = rails.map((s) => s.title.toLowerCase()).join(" \xB7 ");
|
|
2767
|
+
const showRail = railOpen && hasRail;
|
|
2625
2768
|
const [railFocus, setRailFocus] = useState(false);
|
|
2626
2769
|
const [railCursor, setRailCursor] = useState(0);
|
|
2627
|
-
const railRows = sidebar
|
|
2770
|
+
const railRows = railRowsOf(sidebar);
|
|
2628
2771
|
const railActive = showRail && railFocus && railRows.length > 0;
|
|
2629
2772
|
const railAt = Math.min(railCursor, Math.max(0, railRows.length - 1));
|
|
2630
2773
|
const peel = () => {
|
|
2774
|
+
if (palette !== null) return setPalette(null), true;
|
|
2631
2775
|
if (help) return setHelp(false), true;
|
|
2632
2776
|
if (explain) return setExplain(false), true;
|
|
2633
2777
|
if (repoPicker) return setRepoPicker(false), true;
|
|
@@ -2645,8 +2789,8 @@ var BrowseScreen = ({
|
|
|
2645
2789
|
};
|
|
2646
2790
|
});
|
|
2647
2791
|
useEffect(() => {
|
|
2648
|
-
onTyping?.(searchInput);
|
|
2649
|
-
}, [searchInput, onTyping]);
|
|
2792
|
+
onTyping?.(searchInput || palette !== null);
|
|
2793
|
+
}, [searchInput, palette, onTyping]);
|
|
2650
2794
|
const railCols = railWidth(COLS);
|
|
2651
2795
|
const listCols = showRail ? COLS - railCols : COLS;
|
|
2652
2796
|
const [sparkFrame, setSparkFrame] = useState(0);
|
|
@@ -2734,7 +2878,12 @@ var BrowseScreen = ({
|
|
|
2734
2878
|
lastKeyAt.current = Date.now();
|
|
2735
2879
|
if (idleFor >= PULSE_IDLE_MS && sparkKey) setPulseArm((n) => n + 1);
|
|
2736
2880
|
if (hidden) return;
|
|
2881
|
+
if (key.ctrl && input === "k") {
|
|
2882
|
+
setPalette((open) => open === null ? "" : null);
|
|
2883
|
+
return;
|
|
2884
|
+
}
|
|
2737
2885
|
if (key.ctrl || key.meta) return;
|
|
2886
|
+
if (palette !== null) return;
|
|
2738
2887
|
if (help) {
|
|
2739
2888
|
if (helpRange.max > 0) {
|
|
2740
2889
|
const step2 = (n) => setHelpScroll((s) => Math.min(helpRange.max, Math.max(0, s + n)));
|
|
@@ -2792,7 +2941,7 @@ var BrowseScreen = ({
|
|
|
2792
2941
|
setRepoPicker(true);
|
|
2793
2942
|
return;
|
|
2794
2943
|
}
|
|
2795
|
-
if (input === "i" &&
|
|
2944
|
+
if (input === "i" && hasRail) {
|
|
2796
2945
|
setRailOpen((open) => {
|
|
2797
2946
|
if (open) setRailFocus(false);
|
|
2798
2947
|
return !open;
|
|
@@ -2833,6 +2982,13 @@ var BrowseScreen = ({
|
|
|
2833
2982
|
}
|
|
2834
2983
|
return;
|
|
2835
2984
|
}
|
|
2985
|
+
if (input === "c") {
|
|
2986
|
+
const row = railRows[railAt];
|
|
2987
|
+
if (!row?.url) return;
|
|
2988
|
+
clipboard(row.url);
|
|
2989
|
+
showFlash(`\u2713 Copied URL for ${row.key}`);
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2836
2992
|
if (input !== "r" && input !== "q" && !key.leftArrow && !key.rightArrow)
|
|
2837
2993
|
return;
|
|
2838
2994
|
}
|
|
@@ -3091,9 +3247,10 @@ var BrowseScreen = ({
|
|
|
3091
3247
|
// reach a row is worse than a short footer: it names a key that does
|
|
3092
3248
|
// nothing where you are standing.
|
|
3093
3249
|
[
|
|
3094
|
-
["\u2191\u2193", "
|
|
3250
|
+
["\u2191\u2193", "row"],
|
|
3095
3251
|
["\u21B5", "open"],
|
|
3096
3252
|
["o", "browser"],
|
|
3253
|
+
["c", "copy url"],
|
|
3097
3254
|
["\u21E5/esc", "back to list"],
|
|
3098
3255
|
["?", "help"],
|
|
3099
3256
|
["q", "quit"]
|
|
@@ -3111,17 +3268,101 @@ var BrowseScreen = ({
|
|
|
3111
3268
|
["\u2190\u2192", "tab"],
|
|
3112
3269
|
["\u21B5/d", "open"],
|
|
3113
3270
|
["m", "actions"],
|
|
3271
|
+
// Only where Jira is configured: without it the launcher can only say
|
|
3272
|
+
// so, and a footer key that opens an apology is a broken feature.
|
|
3273
|
+
...jiraBase ? [["\u2303K", "launch"]] : [],
|
|
3114
3274
|
// Advertised only where it does something, and named for what it
|
|
3115
3275
|
// shows rather than for the furniture: nobody wants "a sidebar".
|
|
3116
|
-
...showRail ? [["\u21E5",
|
|
3276
|
+
...showRail ? [["\u21E5", railTitle]] : hasRail ? [["i", railTitle]] : [],
|
|
3117
3277
|
["?", "help"],
|
|
3118
3278
|
["q", "quit"]
|
|
3119
3279
|
];
|
|
3120
3280
|
const matchCount = section.items.filter(
|
|
3121
3281
|
(i) => i.kind !== "repo-header" && i.kind !== "subgroup-header"
|
|
3122
3282
|
).length;
|
|
3283
|
+
const launcher = useMemo(() => {
|
|
3284
|
+
const run = /* @__PURE__ */ new Map();
|
|
3285
|
+
if (palette === null)
|
|
3286
|
+
return { items: [], run, message: void 0 };
|
|
3287
|
+
const query = palette.trim();
|
|
3288
|
+
const ticketKey = jiraKeyRe ? query.toUpperCase().match(jiraKeyRe)?.[0] : void 0;
|
|
3289
|
+
const commands = [];
|
|
3290
|
+
const rich = (key, where) => /* @__PURE__ */ jsxs(Text4, { children: [
|
|
3291
|
+
"Open ",
|
|
3292
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, children: key }),
|
|
3293
|
+
" ",
|
|
3294
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: where })
|
|
3295
|
+
] });
|
|
3296
|
+
const labels = /* @__PURE__ */ new Map();
|
|
3297
|
+
if (ticketKey && jiraBase) {
|
|
3298
|
+
const row = {
|
|
3299
|
+
kind: "task",
|
|
3300
|
+
key: ticketKey,
|
|
3301
|
+
ticket: ticketKey,
|
|
3302
|
+
summary: "",
|
|
3303
|
+
url: `${jiraBase}/${ticketKey}`,
|
|
3304
|
+
status: "",
|
|
3305
|
+
age: ""
|
|
3306
|
+
};
|
|
3307
|
+
if (drillExtensionFor(row, extensions)) {
|
|
3308
|
+
commands.push({
|
|
3309
|
+
id: "launcher:here",
|
|
3310
|
+
title: `Open ${ticketKey} here`,
|
|
3311
|
+
run: () => void openDrillView(row)
|
|
3312
|
+
});
|
|
3313
|
+
labels.set("launcher:here", rich(ticketKey, "here"));
|
|
3314
|
+
}
|
|
3315
|
+
commands.push({
|
|
3316
|
+
id: "launcher:jira",
|
|
3317
|
+
title: `Open ${ticketKey} in Jira`,
|
|
3318
|
+
run: () => openInJira(jiraBase, ticketKey, showFlash)
|
|
3319
|
+
});
|
|
3320
|
+
labels.set("launcher:jira", rich(ticketKey, "in Jira"));
|
|
3321
|
+
}
|
|
3322
|
+
const target = {
|
|
3323
|
+
...extensionTargetFor(activeItem),
|
|
3324
|
+
query: palette,
|
|
3325
|
+
ticketKey
|
|
3326
|
+
};
|
|
3327
|
+
for (const ext of extensions ?? []) {
|
|
3328
|
+
for (const command of ext.commands?.(target) ?? []) {
|
|
3329
|
+
commands.push({ ...command, id: `${ext.id}:${command.id}` });
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
for (const command of commands) run.set(command.id, command.run);
|
|
3333
|
+
const message = !jiraBase ? `Jira not configured${jiraSetupHint ? ` \xB7 ${jiraSetupHint}` : ""}` : query && !ticketKey ? `no ticket matches "${query}"` : void 0;
|
|
3334
|
+
const items = commands.map((command) => ({
|
|
3335
|
+
id: command.id,
|
|
3336
|
+
title: command.title,
|
|
3337
|
+
group: command.group,
|
|
3338
|
+
label: labels.get(command.id)
|
|
3339
|
+
}));
|
|
3340
|
+
return { items, run, message };
|
|
3341
|
+
}, [palette, activeItem, extensions, jiraBase, jiraKeyRe, jiraSetupHint]);
|
|
3123
3342
|
if (hidden) return null;
|
|
3124
|
-
const overlay =
|
|
3343
|
+
const overlay = palette !== null ? /* @__PURE__ */ jsx(
|
|
3344
|
+
CommandPalette,
|
|
3345
|
+
{
|
|
3346
|
+
items: launcher.items,
|
|
3347
|
+
query: palette,
|
|
3348
|
+
onQueryChange: setPalette,
|
|
3349
|
+
onSelect: (id) => {
|
|
3350
|
+
const run = launcher.run.get(id);
|
|
3351
|
+
setPalette(null);
|
|
3352
|
+
void run?.();
|
|
3353
|
+
},
|
|
3354
|
+
onClose: () => setPalette(null),
|
|
3355
|
+
message: launcher.message,
|
|
3356
|
+
placeholder: "ticket key\u2026",
|
|
3357
|
+
width: Math.min(60, Math.max(30, listCols - 2)),
|
|
3358
|
+
maxRows: Math.max(3, listHeight - 6),
|
|
3359
|
+
hints: [
|
|
3360
|
+
["\u2191\u2193", "move"],
|
|
3361
|
+
["\u23CE", "open"],
|
|
3362
|
+
["esc", "close"]
|
|
3363
|
+
]
|
|
3364
|
+
}
|
|
3365
|
+
) : help ? /* @__PURE__ */ jsx(
|
|
3125
3366
|
HelpModal,
|
|
3126
3367
|
{
|
|
3127
3368
|
extensions,
|
|
@@ -3138,7 +3379,14 @@ var BrowseScreen = ({
|
|
|
3138
3379
|
selected: repoFilter,
|
|
3139
3380
|
cursor: Math.min(repoCursor, Math.max(0, allRepos.length - 1))
|
|
3140
3381
|
}
|
|
3141
|
-
) : menu.actions && activeItem && activeItem.kind !== "repo-header" ? /* @__PURE__ */ jsx(
|
|
3382
|
+
) : menu.actions && activeItem && activeItem.kind !== "repo-header" ? /* @__PURE__ */ jsx(
|
|
3383
|
+
ActionMenu,
|
|
3384
|
+
{
|
|
3385
|
+
item: activeItem,
|
|
3386
|
+
actions: menu.actions,
|
|
3387
|
+
cursor: menu.cursor
|
|
3388
|
+
}
|
|
3389
|
+
) : null;
|
|
3142
3390
|
return /* @__PURE__ */ jsxs(
|
|
3143
3391
|
Box,
|
|
3144
3392
|
{
|
|
@@ -3166,9 +3414,17 @@ var BrowseScreen = ({
|
|
|
3166
3414
|
}
|
|
3167
3415
|
),
|
|
3168
3416
|
ciStatusState ? /* @__PURE__ */ jsx(CiStatusLine, { state: ciStatusState, job: ciJob }) : null,
|
|
3417
|
+
stripState ? /* @__PURE__ */ jsx(
|
|
3418
|
+
StatusStripLine,
|
|
3419
|
+
{
|
|
3420
|
+
strip: stripState.kind === "ready" ? stripState.strip : void 0,
|
|
3421
|
+
label: stripLabel,
|
|
3422
|
+
width: COLS
|
|
3423
|
+
}
|
|
3424
|
+
) : null,
|
|
3169
3425
|
skippedForBudget ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3170
|
-
/* @__PURE__ */ jsx(
|
|
3171
|
-
/* @__PURE__ */ jsx(
|
|
3426
|
+
/* @__PURE__ */ jsx(Text4, { bold: true, color: colors.accent, children: " \u26A1 auto-refresh paused to save API budget" }),
|
|
3427
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " r refreshes anyway" })
|
|
3172
3428
|
] }) : null,
|
|
3173
3429
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
|
|
3174
3430
|
Tabs,
|
|
@@ -3204,14 +3460,14 @@ var BrowseScreen = ({
|
|
|
3204
3460
|
}
|
|
3205
3461
|
) }),
|
|
3206
3462
|
search != null ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3207
|
-
/* @__PURE__ */ jsx(
|
|
3208
|
-
/* @__PURE__ */ jsx(
|
|
3209
|
-
searchInput ? /* @__PURE__ */ jsx(
|
|
3210
|
-
/* @__PURE__ */ jsx(
|
|
3463
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.info, children: " / " }),
|
|
3464
|
+
/* @__PURE__ */ jsx(Text4, { children: search }),
|
|
3465
|
+
searchInput ? /* @__PURE__ */ jsx(Text4, { color: colors.info, children: "\u258F" }) : null,
|
|
3466
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: ` ${matchCount} match${matchCount !== 1 ? "es" : ""}${searchInput ? " \u21B5 accept \xB7 esc clear" : " esc clear"}` })
|
|
3211
3467
|
] }) : repoFilter.size > 0 ? /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
3212
|
-
/* @__PURE__ */ jsx(
|
|
3213
|
-
/* @__PURE__ */ jsx(
|
|
3214
|
-
/* @__PURE__ */ jsx(
|
|
3468
|
+
/* @__PURE__ */ jsx(Text4, { color: colors.accent, children: " \u25C9 " }),
|
|
3469
|
+
/* @__PURE__ */ jsx(Text4, { children: `${repoFilter.size} repo${repoFilter.size !== 1 ? "s" : ""}` }),
|
|
3470
|
+
/* @__PURE__ */ jsx(Text4, { dimColor: true, children: " f edit \xB7 esc clear" })
|
|
3215
3471
|
] }) : null,
|
|
3216
3472
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
3217
3473
|
/* @__PURE__ */ jsxs(
|
|
@@ -3249,7 +3505,7 @@ var BrowseScreen = ({
|
|
|
3249
3505
|
},
|
|
3250
3506
|
`${viewStart + i}:${rowKey(item)}`
|
|
3251
3507
|
)) }),
|
|
3252
|
-
hasMore && /* @__PURE__ */ jsxs(
|
|
3508
|
+
hasMore && /* @__PURE__ */ jsxs(Text4, { dimColor: true, children: [
|
|
3253
3509
|
" ",
|
|
3254
3510
|
"\u2193 ",
|
|
3255
3511
|
section.items.length - viewStart - visibleCount,
|
|
@@ -3271,10 +3527,10 @@ var BrowseScreen = ({
|
|
|
3271
3527
|
]
|
|
3272
3528
|
}
|
|
3273
3529
|
),
|
|
3274
|
-
showRail
|
|
3530
|
+
showRail ? /* @__PURE__ */ jsx(
|
|
3275
3531
|
SidePanel,
|
|
3276
3532
|
{
|
|
3277
|
-
sidebar,
|
|
3533
|
+
sidebar: rails,
|
|
3278
3534
|
liveLabel,
|
|
3279
3535
|
width: railCols,
|
|
3280
3536
|
height: listHeight,
|
|
@@ -3283,7 +3539,7 @@ var BrowseScreen = ({
|
|
|
3283
3539
|
}
|
|
3284
3540
|
) : null
|
|
3285
3541
|
] }),
|
|
3286
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(
|
|
3542
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: flash ? /* @__PURE__ */ jsx(Text4, { color: colors.success, children: flash }) : /* @__PURE__ */ jsx(FooterHints, { hints }) })
|
|
3287
3543
|
]
|
|
3288
3544
|
}
|
|
3289
3545
|
);
|
|
@@ -3298,7 +3554,7 @@ var NoRowsScreen = ({
|
|
|
3298
3554
|
});
|
|
3299
3555
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3300
3556
|
/* @__PURE__ */ jsx(StatusMessage, { variant: reason === "empty" ? "info" : "error", children: reason === "empty" ? "Nothing open." : `Fetch failed \u2014 ${detail ?? "no reason reported"}` }),
|
|
3301
|
-
reason === "empty" && detail ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
3557
|
+
reason === "empty" && detail ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text4, { dimColor: true, children: detail }) }) : null,
|
|
3302
3558
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
3303
3559
|
FooterHints,
|
|
3304
3560
|
{
|
|
@@ -3323,11 +3579,15 @@ var App = ({
|
|
|
3323
3579
|
origin,
|
|
3324
3580
|
jiraBase,
|
|
3325
3581
|
jiraKeyRe,
|
|
3582
|
+
jiraSetupHint,
|
|
3326
3583
|
jiraTransitions,
|
|
3327
3584
|
hasCiStatus,
|
|
3328
3585
|
ciJob,
|
|
3329
3586
|
ciFetcher,
|
|
3330
3587
|
ciPollMs = 6e4,
|
|
3588
|
+
stripFetcher,
|
|
3589
|
+
stripLabel,
|
|
3590
|
+
stripPollMs = 3e5,
|
|
3331
3591
|
watchPath,
|
|
3332
3592
|
watchDebounceMs = 400,
|
|
3333
3593
|
// Zero by default, deliberately. A package that adds randomness to its own
|
|
@@ -3371,6 +3631,15 @@ var App = ({
|
|
|
3371
3631
|
const next = toCiStatusState(status);
|
|
3372
3632
|
return sameCiStatusState(prev, next) ? prev : next;
|
|
3373
3633
|
});
|
|
3634
|
+
const hasStrip = !!stripFetcher;
|
|
3635
|
+
const [stripState, setStripState] = useState({
|
|
3636
|
+
kind: "loading"
|
|
3637
|
+
});
|
|
3638
|
+
const applyStrip = (strip) => setStripState((prev) => {
|
|
3639
|
+
const next = { kind: "ready", strip };
|
|
3640
|
+
if (prev.kind !== "ready") return next;
|
|
3641
|
+
return stripSignature(prev.strip) === stripSignature(strip) ? prev : next;
|
|
3642
|
+
});
|
|
3374
3643
|
const displayedKey = useRef("");
|
|
3375
3644
|
const displayedSections = useRef([]);
|
|
3376
3645
|
const [transients, setTransients] = useState(NO_TRANSIENTS);
|
|
@@ -3453,13 +3722,10 @@ var App = ({
|
|
|
3453
3722
|
const running = [...heldSince].filter(([tab]) => held.has(tab));
|
|
3454
3723
|
if (running.length === 0) return;
|
|
3455
3724
|
const remaining = (at) => at + TRANSIT_HOLD_MS - Date.now();
|
|
3456
|
-
const timer = setTimeout(
|
|
3457
|
-
(
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
},
|
|
3461
|
-
Math.max(0, Math.min(...running.map(([, at]) => remaining(at))))
|
|
3462
|
-
);
|
|
3725
|
+
const timer = setTimeout(() => {
|
|
3726
|
+
for (const [tab, at] of running)
|
|
3727
|
+
if (remaining(at) <= 0) settleTab(tab, transients);
|
|
3728
|
+
}, Math.max(0, Math.min(...running.map(([, at]) => remaining(at)))));
|
|
3463
3729
|
return () => clearTimeout(timer);
|
|
3464
3730
|
}, [transients, heldSince, state.phase]);
|
|
3465
3731
|
const pendingSummary = useMemo(
|
|
@@ -3567,6 +3833,23 @@ var App = ({
|
|
|
3567
3833
|
clearInterval(id);
|
|
3568
3834
|
};
|
|
3569
3835
|
}, [hasCiStatus, ciFetcher, ciPollMs]);
|
|
3836
|
+
useEffect(() => {
|
|
3837
|
+
if (!stripFetcher) return;
|
|
3838
|
+
let live = true;
|
|
3839
|
+
const poll = () => {
|
|
3840
|
+
stripFetcher().then((strip) => {
|
|
3841
|
+
if (!live) return;
|
|
3842
|
+
applyStrip(strip);
|
|
3843
|
+
}).catch(() => {
|
|
3844
|
+
});
|
|
3845
|
+
};
|
|
3846
|
+
poll();
|
|
3847
|
+
const id = setInterval(poll, stripPollMs);
|
|
3848
|
+
return () => {
|
|
3849
|
+
live = false;
|
|
3850
|
+
clearInterval(id);
|
|
3851
|
+
};
|
|
3852
|
+
}, [stripFetcher, stripPollMs]);
|
|
3570
3853
|
useEffect(() => {
|
|
3571
3854
|
if (!watchPath) return;
|
|
3572
3855
|
const dir = dirname(watchPath);
|
|
@@ -3651,6 +3934,14 @@ var App = ({
|
|
|
3651
3934
|
}
|
|
3652
3935
|
),
|
|
3653
3936
|
hasCiStatus ? /* @__PURE__ */ jsx(CiStatusLine, { state: ciStatusState, job: ciJob }) : null,
|
|
3937
|
+
hasStrip ? /* @__PURE__ */ jsx(
|
|
3938
|
+
StatusStripLine,
|
|
3939
|
+
{
|
|
3940
|
+
strip: stripState.kind === "ready" ? stripState.strip : void 0,
|
|
3941
|
+
label: stripLabel,
|
|
3942
|
+
width: COLS
|
|
3943
|
+
}
|
|
3944
|
+
) : null,
|
|
3654
3945
|
/* @__PURE__ */ jsx(
|
|
3655
3946
|
Box,
|
|
3656
3947
|
{
|
|
@@ -3711,6 +4002,7 @@ var App = ({
|
|
|
3711
4002
|
login: state.login,
|
|
3712
4003
|
jiraBase,
|
|
3713
4004
|
jiraKeyRe,
|
|
4005
|
+
jiraSetupHint,
|
|
3714
4006
|
jiraTransitions,
|
|
3715
4007
|
onRefresh: applyOrRefresh,
|
|
3716
4008
|
onActed,
|
|
@@ -3736,6 +4028,8 @@ var App = ({
|
|
|
3736
4028
|
liveLabel,
|
|
3737
4029
|
ciStatusState: hasCiStatus ? ciStatusState : void 0,
|
|
3738
4030
|
ciJob,
|
|
4031
|
+
stripState: hasStrip ? stripState : void 0,
|
|
4032
|
+
stripLabel,
|
|
3739
4033
|
tabHelp,
|
|
3740
4034
|
onOpenPr: (item) => setState({
|
|
3741
4035
|
phase: "pr",
|
|
@@ -3790,4 +4084,4 @@ var matchesFilter = (repo, filter) => {
|
|
|
3790
4084
|
};
|
|
3791
4085
|
var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
3792
4086
|
|
|
3793
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railWidth, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|
|
4087
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, truncate, useActionMenu, windowCount, withHeaders, withoutItem, workCount, writeCache };
|