@ondrej-svec/hog 1.8.1 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +206 -195
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1998,7 +1998,8 @@ function useKeyboard({
|
|
|
1998
1998
|
selectedIssue,
|
|
1999
1999
|
selectedRepoStatusOptionsLength,
|
|
2000
2000
|
actions,
|
|
2001
|
-
onSearchEscape
|
|
2001
|
+
onSearchEscape,
|
|
2002
|
+
tabNav
|
|
2002
2003
|
}) {
|
|
2003
2004
|
const {
|
|
2004
2005
|
exit,
|
|
@@ -2046,14 +2047,14 @@ function useKeyboard({
|
|
|
2046
2047
|
multiSelect.clear();
|
|
2047
2048
|
ui.clearMultiSelect();
|
|
2048
2049
|
}
|
|
2049
|
-
key.shift ?
|
|
2050
|
+
key.shift ? tabNav.prev() : tabNav.next();
|
|
2050
2051
|
return;
|
|
2051
2052
|
}
|
|
2052
2053
|
}
|
|
2053
2054
|
if (ui.state.mode === "multiSelect") {
|
|
2054
2055
|
if (input2 === " ") {
|
|
2055
2056
|
const id = nav.selectedId;
|
|
2056
|
-
if (id
|
|
2057
|
+
if (id) {
|
|
2057
2058
|
multiSelect.toggle(id);
|
|
2058
2059
|
}
|
|
2059
2060
|
return;
|
|
@@ -2075,6 +2076,11 @@ function useKeyboard({
|
|
|
2075
2076
|
}
|
|
2076
2077
|
if (input2 === "r" && handleErrorAction("retry")) return;
|
|
2077
2078
|
if (ui.canAct) {
|
|
2079
|
+
const digit = parseInt(input2, 10);
|
|
2080
|
+
if (!Number.isNaN(digit) && digit >= 1 && digit <= tabNav.count) {
|
|
2081
|
+
tabNav.jumpTo(digit - 1);
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2078
2084
|
if (input2 === "/") {
|
|
2079
2085
|
multiSelect.clear();
|
|
2080
2086
|
ui.enterSearch();
|
|
@@ -2138,10 +2144,6 @@ function useKeyboard({
|
|
|
2138
2144
|
handleEnterFocus();
|
|
2139
2145
|
return;
|
|
2140
2146
|
}
|
|
2141
|
-
if (input2 === "C") {
|
|
2142
|
-
nav.collapseAll();
|
|
2143
|
-
return;
|
|
2144
|
-
}
|
|
2145
2147
|
if (input2 === "l") {
|
|
2146
2148
|
if (selectedIssue) {
|
|
2147
2149
|
multiSelect.clear();
|
|
@@ -2169,19 +2171,13 @@ function useKeyboard({
|
|
|
2169
2171
|
}
|
|
2170
2172
|
if (input2 === " ") {
|
|
2171
2173
|
const id = nav.selectedId;
|
|
2172
|
-
if (id
|
|
2174
|
+
if (id) {
|
|
2173
2175
|
multiSelect.toggle(id);
|
|
2174
2176
|
ui.enterMultiSelect();
|
|
2175
|
-
} else if (isHeaderId(nav.selectedId)) {
|
|
2176
|
-
nav.toggleSection();
|
|
2177
2177
|
}
|
|
2178
2178
|
return;
|
|
2179
2179
|
}
|
|
2180
2180
|
if (key.return) {
|
|
2181
|
-
if (isHeaderId(nav.selectedId)) {
|
|
2182
|
-
nav.toggleSection();
|
|
2183
|
-
return;
|
|
2184
|
-
}
|
|
2185
2181
|
handleOpen();
|
|
2186
2182
|
return;
|
|
2187
2183
|
}
|
|
@@ -2190,6 +2186,7 @@ function useKeyboard({
|
|
|
2190
2186
|
[
|
|
2191
2187
|
ui,
|
|
2192
2188
|
nav,
|
|
2189
|
+
tabNav,
|
|
2193
2190
|
exit,
|
|
2194
2191
|
refresh,
|
|
2195
2192
|
handleSlack,
|
|
@@ -2228,7 +2225,6 @@ function useKeyboard({
|
|
|
2228
2225
|
var init_use_keyboard = __esm({
|
|
2229
2226
|
"src/board/hooks/use-keyboard.ts"() {
|
|
2230
2227
|
"use strict";
|
|
2231
|
-
init_constants();
|
|
2232
2228
|
}
|
|
2233
2229
|
});
|
|
2234
2230
|
|
|
@@ -2989,14 +2985,7 @@ var init_detail_panel = __esm({
|
|
|
2989
2985
|
// src/board/components/hint-bar.tsx
|
|
2990
2986
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
2991
2987
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2992
|
-
function HintBar({
|
|
2993
|
-
uiMode,
|
|
2994
|
-
multiSelectCount,
|
|
2995
|
-
searchQuery,
|
|
2996
|
-
mineOnly,
|
|
2997
|
-
hasUndoable,
|
|
2998
|
-
onHeader
|
|
2999
|
-
}) {
|
|
2988
|
+
function HintBar({ uiMode, multiSelectCount, searchQuery, mineOnly, hasUndoable }) {
|
|
3000
2989
|
if (uiMode === "multiSelect") {
|
|
3001
2990
|
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3002
2991
|
/* @__PURE__ */ jsxs3(Text3, { color: "cyan", bold: true, children: [
|
|
@@ -3027,20 +3016,9 @@ function HintBar({
|
|
|
3027
3016
|
if (uiMode.startsWith("overlay:")) {
|
|
3028
3017
|
return /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "j/k:nav Enter:select Esc:cancel" }) });
|
|
3029
3018
|
}
|
|
3030
|
-
if (onHeader) {
|
|
3031
|
-
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3032
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "j/k:nav Enter/Space:expand-collapse Tab:next-section C:collapse-all ?:more q:quit" }),
|
|
3033
|
-
mineOnly ? /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: " filter:@me" }) : null,
|
|
3034
|
-
searchQuery ? /* @__PURE__ */ jsxs3(Text3, { color: "yellow", children: [
|
|
3035
|
-
' filter:"',
|
|
3036
|
-
searchQuery,
|
|
3037
|
-
'"'
|
|
3038
|
-
] }) : null
|
|
3039
|
-
] });
|
|
3040
|
-
}
|
|
3041
3019
|
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3042
3020
|
/* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
3043
|
-
"j/k:nav Enter:open m:status c:comment F:find t:@me e:edit
|
|
3021
|
+
"j/k:nav Tab:next-tab 1-9:jump Enter:open m:status c:comment F:find t:@me e:edit",
|
|
3044
3022
|
hasUndoable ? " u:undo" : "",
|
|
3045
3023
|
" ?:more q:quit"
|
|
3046
3024
|
] }),
|
|
@@ -4089,15 +4067,16 @@ var init_help_overlay = __esm({
|
|
|
4089
4067
|
items: [
|
|
4090
4068
|
{ key: "j / Down", desc: "Move down" },
|
|
4091
4069
|
{ key: "k / Up", desc: "Move up" },
|
|
4092
|
-
{ key: "Tab", desc: "Next
|
|
4093
|
-
{ key: "Shift+Tab", desc: "Previous
|
|
4070
|
+
{ key: "Tab", desc: "Next tab" },
|
|
4071
|
+
{ key: "Shift+Tab", desc: "Previous tab" },
|
|
4072
|
+
{ key: "1-9", desc: "Jump to tab by number" }
|
|
4094
4073
|
]
|
|
4095
4074
|
},
|
|
4096
4075
|
{
|
|
4097
4076
|
category: "View",
|
|
4098
4077
|
items: [
|
|
4099
|
-
{ key: "Enter", desc: "
|
|
4100
|
-
{ key: "Space", desc: "
|
|
4078
|
+
{ key: "Enter", desc: "Open issue in browser" },
|
|
4079
|
+
{ key: "Space", desc: "Multi-select item" },
|
|
4101
4080
|
{ key: "/", desc: "Search (inline filter)" },
|
|
4102
4081
|
{ key: "F", desc: "Fuzzy find issue (telescope-style)" },
|
|
4103
4082
|
{ key: "t", desc: "Toggle @me filter (my issues only)" },
|
|
@@ -4126,7 +4105,6 @@ var init_help_overlay = __esm({
|
|
|
4126
4105
|
category: "Board",
|
|
4127
4106
|
items: [
|
|
4128
4107
|
{ key: "L", desc: "Toggle action log" },
|
|
4129
|
-
{ key: "C", desc: "Collapse all sections" },
|
|
4130
4108
|
{ key: "r", desc: "Refresh data" },
|
|
4131
4109
|
{ key: "q", desc: "Quit" }
|
|
4132
4110
|
]
|
|
@@ -4862,9 +4840,16 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4862
4840
|
] })
|
|
4863
4841
|
] });
|
|
4864
4842
|
}
|
|
4865
|
-
return /* @__PURE__ */ jsxs19(
|
|
4866
|
-
|
|
4867
|
-
|
|
4843
|
+
return /* @__PURE__ */ jsxs19(Box18, { children: [
|
|
4844
|
+
/* @__PURE__ */ jsxs19(Text18, { bold: true, color: "white", children: [
|
|
4845
|
+
" ",
|
|
4846
|
+
row.text
|
|
4847
|
+
] }),
|
|
4848
|
+
row.count != null ? /* @__PURE__ */ jsxs19(Text18, { color: "gray", children: [
|
|
4849
|
+
" (",
|
|
4850
|
+
row.count,
|
|
4851
|
+
")"
|
|
4852
|
+
] }) : null
|
|
4868
4853
|
] });
|
|
4869
4854
|
}
|
|
4870
4855
|
case "issue": {
|
|
@@ -4919,23 +4904,45 @@ var init_row_renderer = __esm({
|
|
|
4919
4904
|
}
|
|
4920
4905
|
});
|
|
4921
4906
|
|
|
4907
|
+
// src/board/components/tab-bar.tsx
|
|
4908
|
+
import { Box as Box19, Text as Text19 } from "ink";
|
|
4909
|
+
import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4910
|
+
function TabBar({ tabs, activeTabId, totalWidth }) {
|
|
4911
|
+
return /* @__PURE__ */ jsx20(Box19, { width: totalWidth, children: tabs.map((tab, i) => {
|
|
4912
|
+
const isActive = tab.id === activeTabId;
|
|
4913
|
+
return /* @__PURE__ */ jsx20(Box19, { marginRight: 2, children: /* @__PURE__ */ jsxs20(Text19, { bold: isActive, color: isActive ? "cyan" : "gray", children: [
|
|
4914
|
+
i + 1,
|
|
4915
|
+
":",
|
|
4916
|
+
tab.label,
|
|
4917
|
+
" (",
|
|
4918
|
+
tab.count,
|
|
4919
|
+
")"
|
|
4920
|
+
] }) }, tab.id);
|
|
4921
|
+
}) });
|
|
4922
|
+
}
|
|
4923
|
+
var init_tab_bar = __esm({
|
|
4924
|
+
"src/board/components/tab-bar.tsx"() {
|
|
4925
|
+
"use strict";
|
|
4926
|
+
}
|
|
4927
|
+
});
|
|
4928
|
+
|
|
4922
4929
|
// src/board/components/toast-container.tsx
|
|
4923
4930
|
import { Spinner as Spinner3 } from "@inkjs/ui";
|
|
4924
|
-
import { Box as
|
|
4925
|
-
import { Fragment as Fragment4, jsx as
|
|
4931
|
+
import { Box as Box20, Text as Text20 } from "ink";
|
|
4932
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4926
4933
|
function ToastContainer({ toasts }) {
|
|
4927
4934
|
if (toasts.length === 0) return null;
|
|
4928
|
-
return /* @__PURE__ */
|
|
4929
|
-
/* @__PURE__ */
|
|
4930
|
-
/* @__PURE__ */
|
|
4935
|
+
return /* @__PURE__ */ jsx21(Box20, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx21(Box20, { children: t.type === "loading" ? /* @__PURE__ */ jsxs21(Fragment4, { children: [
|
|
4936
|
+
/* @__PURE__ */ jsx21(Spinner3, { label: "" }),
|
|
4937
|
+
/* @__PURE__ */ jsxs21(Text20, { color: "cyan", children: [
|
|
4931
4938
|
" ",
|
|
4932
4939
|
t.message
|
|
4933
4940
|
] })
|
|
4934
|
-
] }) : /* @__PURE__ */
|
|
4941
|
+
] }) : /* @__PURE__ */ jsxs21(Text20, { color: TYPE_COLORS[t.type], children: [
|
|
4935
4942
|
TYPE_PREFIXES[t.type],
|
|
4936
4943
|
" ",
|
|
4937
4944
|
t.message,
|
|
4938
|
-
t.type === "error" ? /* @__PURE__ */
|
|
4945
|
+
t.type === "error" ? /* @__PURE__ */ jsx21(Text20, { color: "gray", children: t.retry ? " [r]etry [d]ismiss" : " [d]ismiss" }) : null
|
|
4939
4946
|
] }) }, t.id)) });
|
|
4940
4947
|
}
|
|
4941
4948
|
var TYPE_COLORS, TYPE_PREFIXES;
|
|
@@ -4959,9 +4966,9 @@ var init_toast_container = __esm({
|
|
|
4959
4966
|
// src/board/components/dashboard.tsx
|
|
4960
4967
|
import { execFileSync as execFileSync3, spawnSync as spawnSync4 } from "child_process";
|
|
4961
4968
|
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
4962
|
-
import { Box as
|
|
4969
|
+
import { Box as Box21, Text as Text21, useApp, useStdout } from "ink";
|
|
4963
4970
|
import { useCallback as useCallback11, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef13, useState as useState15 } from "react";
|
|
4964
|
-
import { Fragment as Fragment5, jsx as
|
|
4971
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4965
4972
|
function resolveStatusGroups(statusOptions, configuredGroups) {
|
|
4966
4973
|
if (configuredGroups && configuredGroups.length > 0) {
|
|
4967
4974
|
return configuredGroups.map((entry) => {
|
|
@@ -5030,118 +5037,81 @@ function buildBoardTree(repos, tasks, activity) {
|
|
|
5030
5037
|
});
|
|
5031
5038
|
return { activity, sections, tasks };
|
|
5032
5039
|
}
|
|
5033
|
-
function
|
|
5034
|
-
const
|
|
5040
|
+
function buildTabs(tree) {
|
|
5041
|
+
const tabs = tree.sections.map(({ repo, groups }) => ({
|
|
5042
|
+
id: repo.name,
|
|
5043
|
+
label: repo.shortName,
|
|
5044
|
+
count: groups.reduce((s, g) => s + g.issues.length, 0)
|
|
5045
|
+
}));
|
|
5035
5046
|
if (tree.activity.length > 0)
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5047
|
+
tabs.push({ id: "activity", label: "Activity", count: tree.activity.length });
|
|
5048
|
+
if (tree.tasks.length > 0)
|
|
5049
|
+
tabs.push({ id: "ticktick", label: "Tasks", count: tree.tasks.length });
|
|
5050
|
+
return tabs;
|
|
5051
|
+
}
|
|
5052
|
+
function buildNavItemsForTab(tabId, tree) {
|
|
5053
|
+
if (tabId === "activity") return [];
|
|
5054
|
+
if (tabId === "ticktick")
|
|
5055
|
+
return tree.tasks.map((task2) => ({
|
|
5056
|
+
id: `tt:${task2.id}`,
|
|
5057
|
+
section: tabId,
|
|
5058
|
+
type: "item"
|
|
5059
|
+
}));
|
|
5060
|
+
const section = tree.sections.find((s) => s.sectionId === tabId);
|
|
5061
|
+
if (!section) return [];
|
|
5062
|
+
return section.groups.flatMap(
|
|
5063
|
+
(group) => group.issues.map((issue) => ({
|
|
5064
|
+
id: `gh:${section.repo.name}:${issue.number}`,
|
|
5065
|
+
section: tabId,
|
|
5066
|
+
type: "item"
|
|
5067
|
+
}))
|
|
5068
|
+
);
|
|
5057
5069
|
}
|
|
5058
|
-
function
|
|
5070
|
+
function buildFlatRowsForTab(tabId, tree) {
|
|
5071
|
+
if (tabId === "activity")
|
|
5072
|
+
return tree.activity.map((event, i) => ({
|
|
5073
|
+
type: "activity",
|
|
5074
|
+
key: `act:${i}`,
|
|
5075
|
+
navId: null,
|
|
5076
|
+
event
|
|
5077
|
+
}));
|
|
5078
|
+
if (tabId === "ticktick")
|
|
5079
|
+
return tree.tasks.map((task2) => ({
|
|
5080
|
+
type: "task",
|
|
5081
|
+
key: `tt:${task2.id}`,
|
|
5082
|
+
navId: `tt:${task2.id}`,
|
|
5083
|
+
task: task2
|
|
5084
|
+
}));
|
|
5085
|
+
const section = tree.sections.find((s) => s.sectionId === tabId);
|
|
5086
|
+
if (!section) return [];
|
|
5087
|
+
if (section.error)
|
|
5088
|
+
return [{ type: "error", key: `error:${tabId}`, navId: null, text: section.error }];
|
|
5089
|
+
if (section.groups.length === 0)
|
|
5090
|
+
return [
|
|
5091
|
+
{ type: "subHeader", key: `empty:${tabId}`, navId: null, text: "No open issues" }
|
|
5092
|
+
];
|
|
5059
5093
|
const rows = [];
|
|
5060
|
-
|
|
5061
|
-
|
|
5094
|
+
let isFirst = true;
|
|
5095
|
+
for (const group of section.groups) {
|
|
5096
|
+
if (!isFirst)
|
|
5097
|
+
rows.push({ type: "gap", key: `gap:${tabId}:${group.label}`, navId: null });
|
|
5098
|
+
isFirst = false;
|
|
5062
5099
|
rows.push({
|
|
5063
|
-
type: "
|
|
5064
|
-
key:
|
|
5065
|
-
navId:
|
|
5066
|
-
|
|
5067
|
-
count:
|
|
5068
|
-
|
|
5069
|
-
isCollapsed: collapsed
|
|
5100
|
+
type: "subHeader",
|
|
5101
|
+
key: group.subId,
|
|
5102
|
+
navId: null,
|
|
5103
|
+
text: group.label,
|
|
5104
|
+
count: group.issues.length,
|
|
5105
|
+
isCollapsed: false
|
|
5070
5106
|
});
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
const totalIssues = groups.reduce((s, g) => s + g.issues.length, 0);
|
|
5080
|
-
rows.push({
|
|
5081
|
-
type: "sectionHeader",
|
|
5082
|
-
key: `header:${sectionId}`,
|
|
5083
|
-
navId: `header:${sectionId}`,
|
|
5084
|
-
label: repo.shortName,
|
|
5085
|
-
// display label still shows shortName
|
|
5086
|
-
count: totalIssues,
|
|
5087
|
-
countLabel: "issues",
|
|
5088
|
-
isCollapsed: collapsed
|
|
5089
|
-
});
|
|
5090
|
-
if (!collapsed) {
|
|
5091
|
-
if (error) {
|
|
5092
|
-
rows.push({ type: "error", key: `error:${sectionId}`, navId: null, text: error });
|
|
5093
|
-
} else if (groups.length === 0) {
|
|
5094
|
-
rows.push({
|
|
5095
|
-
type: "subHeader",
|
|
5096
|
-
key: `empty:${sectionId}`,
|
|
5097
|
-
navId: null,
|
|
5098
|
-
text: "No open issues"
|
|
5099
|
-
});
|
|
5100
|
-
} else {
|
|
5101
|
-
let isFirstGroup = true;
|
|
5102
|
-
for (const group of groups) {
|
|
5103
|
-
if (!isFirstGroup)
|
|
5104
|
-
rows.push({ type: "gap", key: `gap:${sectionId}:${group.label}`, navId: null });
|
|
5105
|
-
isFirstGroup = false;
|
|
5106
|
-
const subCollapsed = isCollapsed(group.subId);
|
|
5107
|
-
rows.push({
|
|
5108
|
-
type: "subHeader",
|
|
5109
|
-
key: group.subId,
|
|
5110
|
-
navId: group.subId,
|
|
5111
|
-
text: group.label,
|
|
5112
|
-
count: group.issues.length,
|
|
5113
|
-
isCollapsed: subCollapsed
|
|
5114
|
-
});
|
|
5115
|
-
if (!subCollapsed) {
|
|
5116
|
-
for (const issue of group.issues) {
|
|
5117
|
-
rows.push({
|
|
5118
|
-
type: "issue",
|
|
5119
|
-
key: `gh:${repo.name}:${issue.number}`,
|
|
5120
|
-
navId: `gh:${repo.name}:${issue.number}`,
|
|
5121
|
-
issue,
|
|
5122
|
-
repoName: repo.name
|
|
5123
|
-
});
|
|
5124
|
-
}
|
|
5125
|
-
}
|
|
5126
|
-
}
|
|
5127
|
-
}
|
|
5128
|
-
}
|
|
5129
|
-
}
|
|
5130
|
-
if (tree.tasks.length > 0) {
|
|
5131
|
-
const collapsed = isCollapsed("ticktick");
|
|
5132
|
-
rows.push({
|
|
5133
|
-
type: "sectionHeader",
|
|
5134
|
-
key: "header:ticktick",
|
|
5135
|
-
navId: "header:ticktick",
|
|
5136
|
-
label: "Personal (TickTick)",
|
|
5137
|
-
count: tree.tasks.length,
|
|
5138
|
-
countLabel: "tasks",
|
|
5139
|
-
isCollapsed: collapsed
|
|
5140
|
-
});
|
|
5141
|
-
if (!collapsed) {
|
|
5142
|
-
for (const task2 of tree.tasks)
|
|
5143
|
-
rows.push({ type: "task", key: `tt:${task2.id}`, navId: `tt:${task2.id}`, task: task2 });
|
|
5144
|
-
}
|
|
5107
|
+
for (const issue of group.issues)
|
|
5108
|
+
rows.push({
|
|
5109
|
+
type: "issue",
|
|
5110
|
+
key: `gh:${section.repo.name}:${issue.number}`,
|
|
5111
|
+
navId: `gh:${section.repo.name}:${issue.number}`,
|
|
5112
|
+
issue,
|
|
5113
|
+
repoName: section.repo.name
|
|
5114
|
+
});
|
|
5145
5115
|
}
|
|
5146
5116
|
return rows;
|
|
5147
5117
|
}
|
|
@@ -5169,7 +5139,7 @@ function RefreshAge({ lastRefresh }) {
|
|
|
5169
5139
|
return () => clearInterval(id);
|
|
5170
5140
|
}, []);
|
|
5171
5141
|
if (!lastRefresh) return null;
|
|
5172
|
-
return /* @__PURE__ */
|
|
5142
|
+
return /* @__PURE__ */ jsxs22(Text21, { color: refreshAgeColor(lastRefresh), children: [
|
|
5173
5143
|
"Updated ",
|
|
5174
5144
|
timeAgo(lastRefresh)
|
|
5175
5145
|
] });
|
|
@@ -5238,7 +5208,29 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5238
5208
|
() => buildBoardTree(repos, tasks, allActivity),
|
|
5239
5209
|
[repos, tasks, allActivity]
|
|
5240
5210
|
);
|
|
5241
|
-
const
|
|
5211
|
+
const tabs = useMemo3(() => buildTabs(boardTree), [boardTree]);
|
|
5212
|
+
const [activeTabId, setActiveTabId] = useState15(null);
|
|
5213
|
+
const effectiveTabId = activeTabId ?? tabs[0]?.id ?? null;
|
|
5214
|
+
const activeTabIdx = tabs.findIndex((t) => t.id === effectiveTabId);
|
|
5215
|
+
const nextTab = useCallback11(() => {
|
|
5216
|
+
if (tabs.length === 0) return;
|
|
5217
|
+
setActiveTabId(tabs[(Math.max(activeTabIdx, 0) + 1) % tabs.length]?.id ?? null);
|
|
5218
|
+
}, [activeTabIdx, tabs]);
|
|
5219
|
+
const prevTab = useCallback11(() => {
|
|
5220
|
+
if (tabs.length === 0) return;
|
|
5221
|
+
setActiveTabId(tabs[(Math.max(activeTabIdx, 0) - 1 + tabs.length) % tabs.length]?.id ?? null);
|
|
5222
|
+
}, [activeTabIdx, tabs]);
|
|
5223
|
+
const jumpToTab = useCallback11(
|
|
5224
|
+
(idx) => {
|
|
5225
|
+
const tab = tabs[idx];
|
|
5226
|
+
if (tab) setActiveTabId(tab.id);
|
|
5227
|
+
},
|
|
5228
|
+
[tabs]
|
|
5229
|
+
);
|
|
5230
|
+
const navItems = useMemo3(
|
|
5231
|
+
() => buildNavItemsForTab(effectiveTabId ?? "", boardTree),
|
|
5232
|
+
[effectiveTabId, boardTree]
|
|
5233
|
+
);
|
|
5242
5234
|
const nav = useNavigation(navItems);
|
|
5243
5235
|
const getRepoForId = useCallback11((id) => {
|
|
5244
5236
|
if (id.startsWith("gh:")) {
|
|
@@ -5390,10 +5382,15 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5390
5382
|
termSize.rows - CHROME_ROWS - overlayBarRows - toastRows - logPaneRows
|
|
5391
5383
|
);
|
|
5392
5384
|
const flatRows = useMemo3(
|
|
5393
|
-
() =>
|
|
5394
|
-
[
|
|
5385
|
+
() => buildFlatRowsForTab(effectiveTabId ?? "", boardTree),
|
|
5386
|
+
[effectiveTabId, boardTree]
|
|
5395
5387
|
);
|
|
5396
5388
|
const scrollRef = useRef13(0);
|
|
5389
|
+
const prevTabIdRef = useRef13(null);
|
|
5390
|
+
if (effectiveTabId !== prevTabIdRef.current) {
|
|
5391
|
+
prevTabIdRef.current = effectiveTabId;
|
|
5392
|
+
scrollRef.current = 0;
|
|
5393
|
+
}
|
|
5397
5394
|
const selectedRowIdx = useMemo3(
|
|
5398
5395
|
() => flatRows.findIndex((r) => r.navId === nav.selectedId),
|
|
5399
5396
|
[flatRows, nav.selectedId]
|
|
@@ -5404,6 +5401,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5404
5401
|
} else if (selectedRowIdx >= scrollRef.current + viewportHeight) {
|
|
5405
5402
|
scrollRef.current = selectedRowIdx - viewportHeight + 1;
|
|
5406
5403
|
}
|
|
5404
|
+
if (scrollRef.current > 0 && scrollRef.current === selectedRowIdx) {
|
|
5405
|
+
const rowAbove = flatRows[scrollRef.current - 1];
|
|
5406
|
+
if (rowAbove?.type === "subHeader") {
|
|
5407
|
+
scrollRef.current -= 1;
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5407
5410
|
}
|
|
5408
5411
|
const maxOffset = Math.max(0, flatRows.length - viewportHeight);
|
|
5409
5412
|
scrollRef.current = Math.max(0, Math.min(scrollRef.current, maxOffset));
|
|
@@ -5552,6 +5555,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5552
5555
|
const handleFuzzySelect = useCallback11(
|
|
5553
5556
|
(navId) => {
|
|
5554
5557
|
nav.select(navId);
|
|
5558
|
+
if (navId.startsWith("gh:")) {
|
|
5559
|
+
const parts = navId.split(":");
|
|
5560
|
+
if (parts.length >= 3 && parts[1]) setActiveTabId(parts[1]);
|
|
5561
|
+
} else if (navId.startsWith("tt:")) {
|
|
5562
|
+
setActiveTabId("ticktick");
|
|
5563
|
+
}
|
|
5555
5564
|
ui.exitToNormal();
|
|
5556
5565
|
},
|
|
5557
5566
|
[nav, ui]
|
|
@@ -5585,10 +5594,11 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5585
5594
|
handleUndo: undoLast,
|
|
5586
5595
|
handleToggleLog: () => setLogVisible((v) => !v)
|
|
5587
5596
|
},
|
|
5588
|
-
onSearchEscape
|
|
5597
|
+
onSearchEscape,
|
|
5598
|
+
tabNav: { next: nextTab, prev: prevTab, jumpTo: jumpToTab, count: tabs.length }
|
|
5589
5599
|
});
|
|
5590
5600
|
if (status === "loading" && !data) {
|
|
5591
|
-
return /* @__PURE__ */
|
|
5601
|
+
return /* @__PURE__ */ jsx22(Box21, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx22(Spinner4, { label: "Loading dashboard..." }) });
|
|
5592
5602
|
}
|
|
5593
5603
|
const now = data?.fetchedAt ?? /* @__PURE__ */ new Date();
|
|
5594
5604
|
const dateStr = now.toLocaleDateString("en-US", {
|
|
@@ -5596,35 +5606,36 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5596
5606
|
day: "numeric",
|
|
5597
5607
|
year: "numeric"
|
|
5598
5608
|
});
|
|
5599
|
-
return /* @__PURE__ */
|
|
5600
|
-
/* @__PURE__ */
|
|
5601
|
-
/* @__PURE__ */
|
|
5602
|
-
activeProfile ? /* @__PURE__ */
|
|
5609
|
+
return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", paddingX: 1, children: [
|
|
5610
|
+
/* @__PURE__ */ jsxs22(Box21, { children: [
|
|
5611
|
+
/* @__PURE__ */ jsx22(Text21, { color: "cyan", bold: true, children: "HOG BOARD" }),
|
|
5612
|
+
activeProfile ? /* @__PURE__ */ jsxs22(Text21, { color: "yellow", children: [
|
|
5603
5613
|
" [",
|
|
5604
5614
|
activeProfile,
|
|
5605
5615
|
"]"
|
|
5606
5616
|
] }) : null,
|
|
5607
|
-
/* @__PURE__ */
|
|
5617
|
+
/* @__PURE__ */ jsxs22(Text21, { color: "gray", children: [
|
|
5608
5618
|
" ",
|
|
5609
5619
|
"\u2014",
|
|
5610
5620
|
" ",
|
|
5611
5621
|
dateStr
|
|
5612
5622
|
] }),
|
|
5613
|
-
/* @__PURE__ */
|
|
5614
|
-
isRefreshing ? /* @__PURE__ */
|
|
5615
|
-
/* @__PURE__ */
|
|
5616
|
-
/* @__PURE__ */
|
|
5617
|
-
] }) : /* @__PURE__ */
|
|
5618
|
-
/* @__PURE__ */
|
|
5619
|
-
consecutiveFailures > 0 ? /* @__PURE__ */
|
|
5623
|
+
/* @__PURE__ */ jsx22(Text21, { children: " " }),
|
|
5624
|
+
isRefreshing ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
5625
|
+
/* @__PURE__ */ jsx22(Spinner4, { label: "" }),
|
|
5626
|
+
/* @__PURE__ */ jsx22(Text21, { color: "cyan", children: " Refreshing..." })
|
|
5627
|
+
] }) : /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
5628
|
+
/* @__PURE__ */ jsx22(RefreshAge, { lastRefresh }),
|
|
5629
|
+
consecutiveFailures > 0 ? /* @__PURE__ */ jsx22(Text21, { color: "red", children: " (!)" }) : null
|
|
5620
5630
|
] }),
|
|
5621
|
-
autoRefreshPaused ? /* @__PURE__ */
|
|
5631
|
+
autoRefreshPaused ? /* @__PURE__ */ jsx22(Text21, { color: "yellow", children: " Auto-refresh paused \u2014 press r to retry" }) : null
|
|
5622
5632
|
] }),
|
|
5623
|
-
error ? /* @__PURE__ */
|
|
5633
|
+
error ? /* @__PURE__ */ jsxs22(Text21, { color: "red", children: [
|
|
5624
5634
|
"Error: ",
|
|
5625
5635
|
error
|
|
5626
5636
|
] }) : null,
|
|
5627
|
-
/* @__PURE__ */
|
|
5637
|
+
/* @__PURE__ */ jsx22(TabBar, { tabs, activeTabId: effectiveTabId, totalWidth: termSize.cols }),
|
|
5638
|
+
/* @__PURE__ */ jsx22(
|
|
5628
5639
|
OverlayRenderer,
|
|
5629
5640
|
{
|
|
5630
5641
|
uiState: ui.state,
|
|
@@ -5666,16 +5677,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5666
5677
|
onPushEntry: pushEntry
|
|
5667
5678
|
}
|
|
5668
5679
|
),
|
|
5669
|
-
!ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */
|
|
5670
|
-
/* @__PURE__ */
|
|
5671
|
-
hasMoreAbove ? /* @__PURE__ */
|
|
5680
|
+
!ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */ jsxs22(Box21, { height: viewportHeight, children: [
|
|
5681
|
+
/* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", flexGrow: 1, children: [
|
|
5682
|
+
hasMoreAbove ? /* @__PURE__ */ jsxs22(Text21, { color: "gray", dimColor: true, children: [
|
|
5672
5683
|
" ",
|
|
5673
5684
|
"\u25B2",
|
|
5674
5685
|
" ",
|
|
5675
5686
|
aboveCount,
|
|
5676
5687
|
" more above"
|
|
5677
5688
|
] }) : null,
|
|
5678
|
-
visibleRows.map((row) => /* @__PURE__ */
|
|
5689
|
+
visibleRows.map((row) => /* @__PURE__ */ jsx22(
|
|
5679
5690
|
RowRenderer,
|
|
5680
5691
|
{
|
|
5681
5692
|
row,
|
|
@@ -5685,7 +5696,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5685
5696
|
},
|
|
5686
5697
|
row.key
|
|
5687
5698
|
)),
|
|
5688
|
-
hasMoreBelow ? /* @__PURE__ */
|
|
5699
|
+
hasMoreBelow ? /* @__PURE__ */ jsxs22(Text21, { color: "gray", dimColor: true, children: [
|
|
5689
5700
|
" ",
|
|
5690
5701
|
"\u25BC",
|
|
5691
5702
|
" ",
|
|
@@ -5693,7 +5704,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5693
5704
|
" more below"
|
|
5694
5705
|
] }) : null
|
|
5695
5706
|
] }),
|
|
5696
|
-
showDetailPanel ? /* @__PURE__ */
|
|
5707
|
+
showDetailPanel ? /* @__PURE__ */ jsx22(Box21, { marginLeft: 1, width: detailPanelWidth, children: /* @__PURE__ */ jsx22(
|
|
5697
5708
|
DetailPanel,
|
|
5698
5709
|
{
|
|
5699
5710
|
issue: selectedItem.issue,
|
|
@@ -5705,17 +5716,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5705
5716
|
}
|
|
5706
5717
|
) }) : null
|
|
5707
5718
|
] }) : null,
|
|
5708
|
-
/* @__PURE__ */
|
|
5709
|
-
logVisible ? /* @__PURE__ */
|
|
5710
|
-
/* @__PURE__ */
|
|
5719
|
+
/* @__PURE__ */ jsx22(ToastContainer, { toasts }),
|
|
5720
|
+
logVisible ? /* @__PURE__ */ jsx22(ActionLog, { entries: logEntries }) : null,
|
|
5721
|
+
/* @__PURE__ */ jsx22(
|
|
5711
5722
|
HintBar,
|
|
5712
5723
|
{
|
|
5713
5724
|
uiMode: ui.state.mode,
|
|
5714
5725
|
multiSelectCount: multiSelect.count,
|
|
5715
5726
|
searchQuery,
|
|
5716
5727
|
mineOnly,
|
|
5717
|
-
hasUndoable
|
|
5718
|
-
onHeader: isHeaderId(nav.selectedId)
|
|
5728
|
+
hasUndoable
|
|
5719
5729
|
}
|
|
5720
5730
|
)
|
|
5721
5731
|
] });
|
|
@@ -5740,6 +5750,7 @@ var init_dashboard = __esm({
|
|
|
5740
5750
|
init_hint_bar();
|
|
5741
5751
|
init_overlay_renderer();
|
|
5742
5752
|
init_row_renderer();
|
|
5753
|
+
init_tab_bar();
|
|
5743
5754
|
init_toast_container();
|
|
5744
5755
|
PRIORITY_RANK = {
|
|
5745
5756
|
"priority:critical": 0,
|
|
@@ -5747,7 +5758,7 @@ var init_dashboard = __esm({
|
|
|
5747
5758
|
"priority:medium": 2,
|
|
5748
5759
|
"priority:low": 3
|
|
5749
5760
|
};
|
|
5750
|
-
CHROME_ROWS =
|
|
5761
|
+
CHROME_ROWS = 5;
|
|
5751
5762
|
}
|
|
5752
5763
|
});
|
|
5753
5764
|
|
|
@@ -5757,10 +5768,10 @@ __export(live_exports, {
|
|
|
5757
5768
|
runLiveDashboard: () => runLiveDashboard
|
|
5758
5769
|
});
|
|
5759
5770
|
import { render } from "ink";
|
|
5760
|
-
import { jsx as
|
|
5771
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
5761
5772
|
async function runLiveDashboard(config2, options, activeProfile) {
|
|
5762
5773
|
const instance = render(
|
|
5763
|
-
/* @__PURE__ */
|
|
5774
|
+
/* @__PURE__ */ jsx23(Dashboard, { config: config2, options, activeProfile: activeProfile ?? null })
|
|
5764
5775
|
);
|
|
5765
5776
|
setInkInstance(instance);
|
|
5766
5777
|
await instance.waitUntilExit();
|
|
@@ -6923,7 +6934,7 @@ function resolveProjectId(projectId) {
|
|
|
6923
6934
|
process.exit(1);
|
|
6924
6935
|
}
|
|
6925
6936
|
var program = new Command();
|
|
6926
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.
|
|
6937
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.9.1").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
6927
6938
|
const opts = thisCommand.opts();
|
|
6928
6939
|
if (opts.json) setFormat("json");
|
|
6929
6940
|
if (opts.human) setFormat("human");
|