lazyreview 1.0.2 → 1.0.4

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.
Files changed (3) hide show
  1. package/dist/cli.js +1360 -824
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -9601,14 +9601,14 @@ var require_react_reconciler_production = __commonJS({
9601
9601
  }
9602
9602
  var exports2 = {};
9603
9603
  "use strict";
9604
- var React62 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
9604
+ var React63 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
9605
9605
  /* @__PURE__ */ Symbol.for("react.scope");
9606
9606
  var REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity");
9607
9607
  /* @__PURE__ */ Symbol.for("react.legacy_hidden");
9608
9608
  /* @__PURE__ */ Symbol.for("react.tracing_marker");
9609
9609
  var REACT_MEMO_CACHE_SENTINEL = /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel");
9610
9610
  /* @__PURE__ */ Symbol.for("react.view_transition");
9611
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React62.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
9611
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React63.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
9612
9612
  $$$config.cloneMutableInstance;
9613
9613
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
9614
9614
  $$$config.cloneMutableTextInstance;
@@ -22201,14 +22201,14 @@ var require_react_reconciler_development = __commonJS({
22201
22201
  }
22202
22202
  var exports2 = {};
22203
22203
  "use strict";
22204
- var React62 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
22204
+ var React63 = require_react(), Scheduler2 = require_scheduler(), assign = Object.assign, REACT_LEGACY_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
22205
22205
  /* @__PURE__ */ Symbol.for("react.scope");
22206
22206
  var REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity");
22207
22207
  /* @__PURE__ */ Symbol.for("react.legacy_hidden");
22208
22208
  /* @__PURE__ */ Symbol.for("react.tracing_marker");
22209
22209
  var REACT_MEMO_CACHE_SENTINEL = /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel");
22210
22210
  /* @__PURE__ */ Symbol.for("react.view_transition");
22211
- var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React62.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
22211
+ var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React63.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
22212
22212
  $$$config.cloneMutableInstance;
22213
22213
  var appendInitialChild = $$$config.appendInitialChild, finalizeInitialChildren = $$$config.finalizeInitialChildren, shouldSetTextContent = $$$config.shouldSetTextContent, createTextInstance = $$$config.createTextInstance;
22214
22214
  $$$config.cloneMutableTextInstance;
@@ -24835,18 +24835,18 @@ var require_react_jsx_runtime_development = __commonJS({
24835
24835
  function isValidElement3(object2) {
24836
24836
  return "object" === typeof object2 && null !== object2 && object2.$$typeof === REACT_ELEMENT_TYPE;
24837
24837
  }
24838
- var React62 = require_react(), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), ReactSharedInternals = React62.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
24838
+ var React63 = require_react(), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), ReactSharedInternals = React63.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
24839
24839
  return null;
24840
24840
  };
24841
- React62 = {
24841
+ React63 = {
24842
24842
  react_stack_bottom_frame: function(callStackForError) {
24843
24843
  return callStackForError();
24844
24844
  }
24845
24845
  };
24846
24846
  var specialPropKeyWarningShown;
24847
24847
  var didWarnAboutElementRef = {};
24848
- var unknownOwnerDebugStack = React62.react_stack_bottom_frame.bind(
24849
- React62,
24848
+ var unknownOwnerDebugStack = React63.react_stack_bottom_frame.bind(
24849
+ React63,
24850
24850
  UnknownOwner
24851
24851
  )();
24852
24852
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -83064,7 +83064,7 @@ var measureElement = (node) => ({
83064
83064
  var measure_element_default = measureElement;
83065
83065
 
83066
83066
  // src/app.tsx
83067
- var import_react102 = __toESM(require_react(), 1);
83067
+ var import_react105 = __toESM(require_react(), 1);
83068
83068
 
83069
83069
  // node_modules/.pnpm/@tanstack+query-core@5.90.20/node_modules/@tanstack/query-core/build/modern/subscribable.js
83070
83070
  var Subscribable = class {
@@ -85987,13 +85987,47 @@ function getThemeByName(name) {
85987
85987
  }
85988
85988
 
85989
85989
  // src/components/layout/TopBar.tsx
85990
+ var import_react30 = __toESM(require_react(), 1);
85990
85991
  var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
85992
+ function connectionColor(status) {
85993
+ switch (status) {
85994
+ case "connected":
85995
+ return "green";
85996
+ case "rate-limited":
85997
+ return "yellow";
85998
+ case "error":
85999
+ return "red";
86000
+ }
86001
+ }
86002
+ function connectionLabel(status) {
86003
+ switch (status) {
86004
+ case "connected":
86005
+ return "connected";
86006
+ case "rate-limited":
86007
+ return "rate limited";
86008
+ case "error":
86009
+ return "disconnected";
86010
+ }
86011
+ }
86012
+ function truncate(text, maxLen) {
86013
+ if (text.length <= maxLen) return text;
86014
+ return `${text.slice(0, maxLen - 1)}~`;
86015
+ }
85991
86016
  function TopBar({
85992
86017
  username,
85993
86018
  provider,
85994
- repoPath
86019
+ repoPath,
86020
+ screenName,
86021
+ prTitle,
86022
+ prNumber,
86023
+ connectionStatus = "connected"
85995
86024
  }) {
85996
86025
  const theme14 = useTheme();
86026
+ const breadcrumbs = [
86027
+ "LazyReview",
86028
+ ...screenName ? [screenName] : repoPath ? [repoPath] : [],
86029
+ ...prNumber !== void 0 && prTitle ? [`PR #${prNumber}: ${truncate(prTitle, 40)}`] : []
86030
+ ];
85997
86031
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
85998
86032
  Box_default,
85999
86033
  {
@@ -86003,14 +86037,25 @@ function TopBar({
86003
86037
  paddingX: 1,
86004
86038
  marginTop: 0.6,
86005
86039
  children: [
86040
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { gap: 0, children: breadcrumbs.map((segment, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react30.default.Fragment, { children: [
86041
+ i > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: theme14.colors.muted, children: [
86042
+ " ",
86043
+ ">",
86044
+ " "
86045
+ ] }),
86046
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
86047
+ Text,
86048
+ {
86049
+ color: i === 0 ? theme14.colors.accent : theme14.colors.text,
86050
+ bold: i === 0,
86051
+ children: segment
86052
+ }
86053
+ )
86054
+ ] }, i)) }),
86006
86055
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { gap: 1, children: [
86007
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.accent, bold: true, children: "LazyReview" }),
86008
- repoPath && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
86009
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.muted, children: "\u2502" }),
86010
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.text, children: repoPath })
86011
- ] })
86012
- ] }),
86013
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { gap: 1, children: [
86056
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: connectionColor(connectionStatus), children: "\u25CF" }),
86057
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.muted, children: connectionLabel(connectionStatus) }),
86058
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.muted, children: "\u2502" }),
86014
86059
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.muted, children: provider }),
86015
86060
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.muted, children: "\u2502" }),
86016
86061
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: theme14.colors.secondary, children: username })
@@ -86020,6 +86065,49 @@ function TopBar({
86020
86065
  );
86021
86066
  }
86022
86067
 
86068
+ // src/hooks/useSidebarSections.ts
86069
+ var import_react31 = __toESM(require_react(), 1);
86070
+ var SIDEBAR_SECTIONS = [
86071
+ { name: "Reviews", itemIndices: [0, 1, 2, 3] },
86072
+ { name: "App", itemIndices: [4] }
86073
+ ];
86074
+ function useSidebarSections() {
86075
+ const [collapsedSections, setCollapsedSections] = (0, import_react31.useState)(
86076
+ /* @__PURE__ */ new Set()
86077
+ );
86078
+ const toggleSection = (0, import_react31.useCallback)((sectionName) => {
86079
+ setCollapsedSections((prev) => {
86080
+ const next = new Set(prev);
86081
+ if (next.has(sectionName)) {
86082
+ next.delete(sectionName);
86083
+ } else {
86084
+ next.add(sectionName);
86085
+ }
86086
+ return next;
86087
+ });
86088
+ }, []);
86089
+ const navigableEntries = (0, import_react31.useMemo)(() => {
86090
+ const entries2 = [];
86091
+ for (const section of SIDEBAR_SECTIONS) {
86092
+ entries2.push({ type: "section", sectionName: section.name });
86093
+ if (!collapsedSections.has(section.name)) {
86094
+ for (const idx of section.itemIndices) {
86095
+ entries2.push({ type: "item", itemIndex: idx });
86096
+ }
86097
+ }
86098
+ }
86099
+ return entries2;
86100
+ }, [collapsedSections]);
86101
+ return {
86102
+ collapsedSections,
86103
+ toggleSection,
86104
+ navigableEntries
86105
+ };
86106
+ }
86107
+ function getItemIndex(entry) {
86108
+ return entry.type === "item" ? entry.itemIndex : null;
86109
+ }
86110
+
86023
86111
  // src/components/layout/Sidebar.tsx
86024
86112
  var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
86025
86113
  var SIDEBAR_ITEMS = [
@@ -86036,45 +86124,162 @@ var sidebarIcons = {
86036
86124
  "This Repo": "\u25C8",
86037
86125
  Settings: "\u2699"
86038
86126
  };
86127
+ function getCountForItem(label, counts) {
86128
+ if (!counts) return null;
86129
+ switch (label) {
86130
+ case "Involved":
86131
+ return counts.involved;
86132
+ case "My PRs":
86133
+ return counts.myPrs;
86134
+ case "For Review":
86135
+ return counts.forReview;
86136
+ case "This Repo":
86137
+ return counts.thisRepo;
86138
+ case "Settings":
86139
+ return null;
86140
+ }
86141
+ }
86142
+ function getUnreadForItem(label, counts) {
86143
+ if (!counts) return null;
86144
+ if (label === "For Review") return counts.forReviewUnread;
86145
+ return null;
86146
+ }
86039
86147
  function Sidebar({
86040
86148
  selectedIndex,
86041
86149
  visible,
86042
- isActive: isActive2
86150
+ isActive: isActive2,
86151
+ counts,
86152
+ collapsedSections,
86153
+ navigableEntries,
86154
+ navIndex
86043
86155
  }) {
86044
86156
  const theme14 = useTheme();
86045
86157
  if (!visible) return null;
86158
+ const hasSections = collapsedSections !== void 0 && navigableEntries !== void 0;
86159
+ const currentNavEntry = hasSections && navIndex !== void 0 ? navigableEntries[navIndex] : void 0;
86046
86160
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
86047
86161
  Box_default,
86048
86162
  {
86049
86163
  flexDirection: "column",
86050
- width: 24,
86164
+ width: 28,
86051
86165
  borderStyle: "single",
86052
86166
  borderColor: isActive2 ? theme14.colors.accent : theme14.colors.border,
86053
86167
  children: [
86054
86168
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { paddingX: 1, paddingY: 0, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: theme14.colors.accent, bold: isActive2, dimColor: !isActive2, children: "Navigation" }) }),
86055
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "column", paddingTop: 1, children: SIDEBAR_ITEMS.map((label, index) => {
86056
- const isSelected = index === selectedIndex;
86057
- const icon = sidebarIcons[label];
86058
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
86059
- Text,
86060
- {
86061
- color: isSelected ? theme14.colors.accent : theme14.colors.text,
86062
- backgroundColor: isSelected ? theme14.colors.selection : void 0,
86063
- bold: isSelected,
86064
- dimColor: !isActive2 && !isSelected,
86065
- children: [
86066
- isSelected ? "\u25B8 " : " ",
86067
- icon,
86068
- " ",
86069
- label
86070
- ]
86071
- }
86072
- ) }, label);
86073
- }) })
86169
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "column", paddingTop: 1, children: hasSections ? renderSections(
86170
+ collapsedSections,
86171
+ selectedIndex,
86172
+ isActive2,
86173
+ theme14,
86174
+ counts,
86175
+ currentNavEntry
86176
+ ) : renderFlatItems(selectedIndex, isActive2, theme14, counts) })
86074
86177
  ]
86075
86178
  }
86076
86179
  );
86077
86180
  }
86181
+ function renderSections(collapsedSections, selectedItemIndex, isActive2, theme14, counts, currentNavEntry) {
86182
+ const elements = [];
86183
+ for (const section of SIDEBAR_SECTIONS) {
86184
+ const isCollapsed = collapsedSections.has(section.name);
86185
+ const isSectionSelected = currentNavEntry?.type === "section" && currentNavEntry.sectionName === section.name;
86186
+ elements.push(
86187
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
86188
+ Text,
86189
+ {
86190
+ color: isSectionSelected ? theme14.colors.accent : theme14.colors.secondary,
86191
+ bold: true,
86192
+ backgroundColor: isSectionSelected ? theme14.colors.selection : void 0,
86193
+ children: [
86194
+ isSectionSelected ? "\u25B8 " : " ",
86195
+ isCollapsed ? "\u25B8" : "\u25BE",
86196
+ " ",
86197
+ section.name
86198
+ ]
86199
+ }
86200
+ ) }, `section-${section.name}`)
86201
+ );
86202
+ if (!isCollapsed) {
86203
+ for (const idx of section.itemIndices) {
86204
+ const label = SIDEBAR_ITEMS[idx];
86205
+ if (!label) continue;
86206
+ const isSelected = currentNavEntry?.type === "item" && currentNavEntry.itemIndex === idx;
86207
+ const icon = sidebarIcons[label];
86208
+ const count = getCountForItem(label, counts);
86209
+ const unread = getUnreadForItem(label, counts);
86210
+ elements.push(
86211
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { paddingX: 1, marginLeft: 1, children: [
86212
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
86213
+ Text,
86214
+ {
86215
+ color: isSelected ? theme14.colors.accent : theme14.colors.text,
86216
+ backgroundColor: isSelected ? theme14.colors.selection : void 0,
86217
+ bold: isSelected,
86218
+ dimColor: !isActive2 && !isSelected,
86219
+ children: [
86220
+ isSelected ? "\u25B8 " : " ",
86221
+ icon,
86222
+ " ",
86223
+ label
86224
+ ]
86225
+ }
86226
+ ),
86227
+ count !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: theme14.colors.muted, children: [
86228
+ " ",
86229
+ "(",
86230
+ count,
86231
+ ")"
86232
+ ] }),
86233
+ unread !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: theme14.colors.accent, children: [
86234
+ " ",
86235
+ "*",
86236
+ unread,
86237
+ " new*"
86238
+ ] })
86239
+ ] }, label)
86240
+ );
86241
+ }
86242
+ }
86243
+ }
86244
+ return elements;
86245
+ }
86246
+ function renderFlatItems(selectedIndex, isActive2, theme14, counts) {
86247
+ return SIDEBAR_ITEMS.map((label, index) => {
86248
+ const isSelected = index === selectedIndex;
86249
+ const icon = sidebarIcons[label];
86250
+ const count = getCountForItem(label, counts);
86251
+ const unread = getUnreadForItem(label, counts);
86252
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { paddingX: 1, children: [
86253
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
86254
+ Text,
86255
+ {
86256
+ color: isSelected ? theme14.colors.accent : theme14.colors.text,
86257
+ backgroundColor: isSelected ? theme14.colors.selection : void 0,
86258
+ bold: isSelected,
86259
+ dimColor: !isActive2 && !isSelected,
86260
+ children: [
86261
+ isSelected ? "\u25B8 " : " ",
86262
+ icon,
86263
+ " ",
86264
+ label
86265
+ ]
86266
+ }
86267
+ ),
86268
+ count !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: theme14.colors.muted, children: [
86269
+ " ",
86270
+ "(",
86271
+ count,
86272
+ ")"
86273
+ ] }),
86274
+ unread !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: theme14.colors.accent, children: [
86275
+ " ",
86276
+ "*",
86277
+ unread,
86278
+ " new*"
86279
+ ] })
86280
+ ] }, label);
86281
+ });
86282
+ }
86078
86283
 
86079
86284
  // src/components/layout/MainPanel.tsx
86080
86285
  var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
@@ -86096,7 +86301,7 @@ function MainPanel({
86096
86301
  }
86097
86302
 
86098
86303
  // src/hooks/useStatusMessage.ts
86099
- var import_react30 = __toESM(require_react(), 1);
86304
+ var import_react32 = __toESM(require_react(), 1);
86100
86305
  function createStatusMessageStore() {
86101
86306
  let message = null;
86102
86307
  let listeners2 = [];
@@ -86133,12 +86338,12 @@ function createStatusMessageStore() {
86133
86338
  }
86134
86339
  var store = createStatusMessageStore();
86135
86340
  function useStatusMessage() {
86136
- const message = (0, import_react30.useSyncExternalStore)(
86341
+ const message = (0, import_react32.useSyncExternalStore)(
86137
86342
  store.subscribe,
86138
86343
  store.getSnapshot,
86139
86344
  () => null
86140
86345
  );
86141
- const setStatusMessage = (0, import_react30.useCallback)(
86346
+ const setStatusMessage = (0, import_react32.useCallback)(
86142
86347
  (msg, durationMs) => {
86143
86348
  store.setMessage(msg, durationMs);
86144
86349
  },
@@ -86148,7 +86353,7 @@ function useStatusMessage() {
86148
86353
  }
86149
86354
 
86150
86355
  // src/hooks/useLastUpdated.ts
86151
- var import_react31 = __toESM(require_react(), 1);
86356
+ var import_react33 = __toESM(require_react(), 1);
86152
86357
  function createLastUpdatedStore() {
86153
86358
  let updatedAt = null;
86154
86359
  let listeners2 = [];
@@ -86176,19 +86381,19 @@ function touchLastUpdated() {
86176
86381
  store2.touch();
86177
86382
  }
86178
86383
  function useLastUpdated() {
86179
- const updatedAt = (0, import_react31.useSyncExternalStore)(
86384
+ const updatedAt = (0, import_react33.useSyncExternalStore)(
86180
86385
  store2.subscribe,
86181
86386
  store2.getSnapshot,
86182
86387
  () => null
86183
86388
  );
86184
- const [now2, setNow] = (0, import_react31.useState)(Date.now());
86185
- (0, import_react31.useEffect)(() => {
86389
+ const [now2, setNow] = (0, import_react33.useState)(Date.now());
86390
+ (0, import_react33.useEffect)(() => {
86186
86391
  const timer = setInterval(() => {
86187
86392
  setNow(Date.now());
86188
86393
  }, 1e3);
86189
86394
  return () => clearInterval(timer);
86190
86395
  }, []);
86191
- const touch = (0, import_react31.useCallback)(() => {
86396
+ const touch = (0, import_react33.useCallback)(() => {
86192
86397
  store2.touch();
86193
86398
  }, []);
86194
86399
  const label = formatElapsed(updatedAt, now2);
@@ -86206,7 +86411,7 @@ function formatElapsed(updatedAt, now2) {
86206
86411
  }
86207
86412
 
86208
86413
  // src/hooks/useRateLimit.ts
86209
- var import_react32 = __toESM(require_react(), 1);
86414
+ var import_react34 = __toESM(require_react(), 1);
86210
86415
  var DEFAULT_RATE_LIMIT = {
86211
86416
  remaining: 5e3,
86212
86417
  limit: 5e3,
@@ -86253,7 +86458,7 @@ function updateRateLimit(headers) {
86253
86458
  }
86254
86459
  }
86255
86460
  function useRateLimit() {
86256
- return (0, import_react32.useSyncExternalStore)(
86461
+ return (0, import_react34.useSyncExternalStore)(
86257
86462
  store3.subscribe,
86258
86463
  store3.getSnapshot,
86259
86464
  () => DEFAULT_RATE_LIMIT
@@ -86327,7 +86532,7 @@ function StatusBar({
86327
86532
  }
86328
86533
 
86329
86534
  // src/hooks/useScreenContext.ts
86330
- var import_react33 = __toESM(require_react(), 1);
86535
+ var import_react35 = __toESM(require_react(), 1);
86331
86536
  var current = void 0;
86332
86537
  var listeners = [];
86333
86538
  function notify() {
@@ -86349,7 +86554,7 @@ function setScreenContext(context6) {
86349
86554
  }
86350
86555
  }
86351
86556
  function useScreenContext() {
86352
- return (0, import_react33.useSyncExternalStore)(subscribe, getSnapshot, () => void 0);
86557
+ return (0, import_react35.useSyncExternalStore)(subscribe, getSnapshot, () => void 0);
86353
86558
  }
86354
86559
 
86355
86560
  // src/components/common/Divider.tsx
@@ -86494,13 +86699,13 @@ function HelpModal({ onClose }) {
86494
86699
  }
86495
86700
 
86496
86701
  // src/components/layout/TokenInputModal.tsx
86497
- var import_react66 = __toESM(require_react(), 1);
86702
+ var import_react68 = __toESM(require_react(), 1);
86498
86703
 
86499
86704
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/badge/badge.js
86500
- var import_react35 = __toESM(require_react(), 1);
86705
+ var import_react37 = __toESM(require_react(), 1);
86501
86706
 
86502
86707
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/theme.js
86503
- var import_react34 = __toESM(require_react(), 1);
86708
+ var import_react36 = __toESM(require_react(), 1);
86504
86709
  var import_deepmerge = __toESM(require_cjs(), 1);
86505
86710
 
86506
86711
  // node_modules/.pnpm/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js
@@ -87084,58 +87289,58 @@ var defaultTheme2 = {
87084
87289
  PasswordInput: theme_default13
87085
87290
  }
87086
87291
  };
87087
- var ThemeContext2 = (0, import_react34.createContext)(defaultTheme2);
87292
+ var ThemeContext2 = (0, import_react36.createContext)(defaultTheme2);
87088
87293
  var useComponentTheme = (component) => {
87089
- const theme14 = (0, import_react34.useContext)(ThemeContext2);
87294
+ const theme14 = (0, import_react36.useContext)(ThemeContext2);
87090
87295
  return theme14.components[component];
87091
87296
  };
87092
87297
 
87093
87298
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/confirm-input/confirm-input.js
87094
- var import_react36 = __toESM(require_react(), 1);
87299
+ var import_react38 = __toESM(require_react(), 1);
87095
87300
 
87096
87301
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list.js
87097
- var import_react40 = __toESM(require_react(), 1);
87302
+ var import_react42 = __toESM(require_react(), 1);
87098
87303
 
87099
87304
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list-item.js
87100
- var import_react38 = __toESM(require_react(), 1);
87305
+ var import_react40 = __toESM(require_react(), 1);
87101
87306
 
87102
87307
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list-item-context.js
87103
- var import_react37 = __toESM(require_react(), 1);
87308
+ var import_react39 = __toESM(require_react(), 1);
87104
87309
 
87105
87310
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/constants.js
87106
87311
  var defaultMarker = figures_default.line;
87107
87312
 
87108
87313
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list-item-context.js
87109
- var UnorderedListItemContext = (0, import_react37.createContext)({
87314
+ var UnorderedListItemContext = (0, import_react39.createContext)({
87110
87315
  marker: defaultMarker
87111
87316
  });
87112
87317
 
87113
87318
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list-item.js
87114
87319
  function UnorderedListItem({ children }) {
87115
- const { marker } = (0, import_react38.useContext)(UnorderedListItemContext);
87320
+ const { marker } = (0, import_react40.useContext)(UnorderedListItemContext);
87116
87321
  const { styles: styles5 } = useComponentTheme("UnorderedList");
87117
- return import_react38.default.createElement(
87322
+ return import_react40.default.createElement(
87118
87323
  Box_default,
87119
87324
  { ...styles5.listItem() },
87120
- import_react38.default.createElement(Text, { ...styles5.marker() }, marker),
87121
- import_react38.default.createElement(Box_default, { ...styles5.content() }, children)
87325
+ import_react40.default.createElement(Text, { ...styles5.marker() }, marker),
87326
+ import_react40.default.createElement(Box_default, { ...styles5.content() }, children)
87122
87327
  );
87123
87328
  }
87124
87329
 
87125
87330
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list-context.js
87126
- var import_react39 = __toESM(require_react(), 1);
87127
- var UnorderedListContext = (0, import_react39.createContext)({
87331
+ var import_react41 = __toESM(require_react(), 1);
87332
+ var UnorderedListContext = (0, import_react41.createContext)({
87128
87333
  depth: 0
87129
87334
  });
87130
87335
 
87131
87336
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/unordered-list/unordered-list.js
87132
87337
  function UnorderedList({ children }) {
87133
- const { depth } = (0, import_react40.useContext)(UnorderedListContext);
87338
+ const { depth } = (0, import_react42.useContext)(UnorderedListContext);
87134
87339
  const { styles: styles5, config: config2 } = useComponentTheme("UnorderedList");
87135
- const listContext = (0, import_react40.useMemo)(() => ({
87340
+ const listContext = (0, import_react42.useMemo)(() => ({
87136
87341
  depth: depth + 1
87137
87342
  }), [depth]);
87138
- const listItemContext = (0, import_react40.useMemo)(() => {
87343
+ const listItemContext = (0, import_react42.useMemo)(() => {
87139
87344
  const { marker } = config2();
87140
87345
  if (typeof marker === "string") {
87141
87346
  return { marker };
@@ -87149,46 +87354,46 @@ function UnorderedList({ children }) {
87149
87354
  marker: defaultMarker
87150
87355
  };
87151
87356
  }, [config2, depth]);
87152
- return import_react40.default.createElement(
87357
+ return import_react42.default.createElement(
87153
87358
  UnorderedListContext.Provider,
87154
87359
  { value: listContext },
87155
- import_react40.default.createElement(
87360
+ import_react42.default.createElement(
87156
87361
  UnorderedListItemContext.Provider,
87157
87362
  { value: listItemContext },
87158
- import_react40.default.createElement(Box_default, { ...styles5.list() }, children)
87363
+ import_react42.default.createElement(Box_default, { ...styles5.list() }, children)
87159
87364
  )
87160
87365
  );
87161
87366
  }
87162
87367
  UnorderedList.Item = UnorderedListItem;
87163
87368
 
87164
87369
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/multi-select/multi-select.js
87165
- var import_react43 = __toESM(require_react(), 1);
87370
+ var import_react45 = __toESM(require_react(), 1);
87166
87371
 
87167
87372
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/multi-select/multi-select-option.js
87168
- var import_react41 = __toESM(require_react(), 1);
87373
+ var import_react43 = __toESM(require_react(), 1);
87169
87374
 
87170
87375
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/multi-select/use-multi-select-state.js
87171
- var import_react42 = __toESM(require_react(), 1);
87376
+ var import_react44 = __toESM(require_react(), 1);
87172
87377
  import { isDeepStrictEqual } from "util";
87173
87378
 
87174
87379
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/progress-bar/progress-bar.js
87175
- var import_react44 = __toESM(require_react(), 1);
87380
+ var import_react46 = __toESM(require_react(), 1);
87176
87381
 
87177
87382
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/select/select.js
87178
- var import_react47 = __toESM(require_react(), 1);
87383
+ var import_react49 = __toESM(require_react(), 1);
87179
87384
 
87180
87385
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/select/select-option.js
87181
- var import_react45 = __toESM(require_react(), 1);
87386
+ var import_react47 = __toESM(require_react(), 1);
87182
87387
 
87183
87388
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/select/use-select-state.js
87184
- var import_react46 = __toESM(require_react(), 1);
87389
+ var import_react48 = __toESM(require_react(), 1);
87185
87390
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
87186
87391
 
87187
87392
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/spinner/spinner.js
87188
- var import_react49 = __toESM(require_react(), 1);
87393
+ var import_react51 = __toESM(require_react(), 1);
87189
87394
 
87190
87395
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/spinner/use-spinner.js
87191
- var import_react48 = __toESM(require_react(), 1);
87396
+ var import_react50 = __toESM(require_react(), 1);
87192
87397
 
87193
87398
  // node_modules/.pnpm/cli-spinners@3.4.0/node_modules/cli-spinners/spinners.json
87194
87399
  var spinners_default = {
@@ -88895,9 +89100,9 @@ var spinnersList = Object.keys(spinners_default);
88895
89100
 
88896
89101
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/spinner/use-spinner.js
88897
89102
  function useSpinner({ type: type3 = "dots" }) {
88898
- const [frame, setFrame] = (0, import_react48.useState)(0);
89103
+ const [frame, setFrame] = (0, import_react50.useState)(0);
88899
89104
  const spinner = cli_spinners_default[type3];
88900
- (0, import_react48.useEffect)(() => {
89105
+ (0, import_react50.useEffect)(() => {
88901
89106
  const timer = setInterval(() => {
88902
89107
  setFrame((previousFrame) => {
88903
89108
  const isLastFrame = previousFrame === spinner.frames.length - 1;
@@ -88917,19 +89122,19 @@ function useSpinner({ type: type3 = "dots" }) {
88917
89122
  function Spinner({ label, type: type3 }) {
88918
89123
  const { frame } = useSpinner({ type: type3 });
88919
89124
  const { styles: styles5 } = useComponentTheme("Spinner");
88920
- return import_react49.default.createElement(
89125
+ return import_react51.default.createElement(
88921
89126
  Box_default,
88922
89127
  { ...styles5.container() },
88923
- import_react49.default.createElement(Text, { ...styles5.frame() }, frame),
88924
- label && import_react49.default.createElement(Text, { ...styles5.label() }, label)
89128
+ import_react51.default.createElement(Text, { ...styles5.frame() }, frame),
89129
+ label && import_react51.default.createElement(Text, { ...styles5.label() }, label)
88925
89130
  );
88926
89131
  }
88927
89132
 
88928
89133
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/text-input/text-input.js
88929
- var import_react52 = __toESM(require_react(), 1);
89134
+ var import_react54 = __toESM(require_react(), 1);
88930
89135
 
88931
89136
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/text-input/use-text-input-state.js
88932
- var import_react50 = __toESM(require_react(), 1);
89137
+ var import_react52 = __toESM(require_react(), 1);
88933
89138
  var reducer = (state, action) => {
88934
89139
  switch (action.type) {
88935
89140
  case "move-cursor-left": {
@@ -88964,39 +89169,39 @@ var reducer = (state, action) => {
88964
89169
  }
88965
89170
  };
88966
89171
  var useTextInputState = ({ defaultValue = "", suggestions, onChange, onSubmit }) => {
88967
- const [state, dispatch] = (0, import_react50.useReducer)(reducer, {
89172
+ const [state, dispatch] = (0, import_react52.useReducer)(reducer, {
88968
89173
  previousValue: defaultValue,
88969
89174
  value: defaultValue,
88970
89175
  cursorOffset: defaultValue.length
88971
89176
  });
88972
- const suggestion = (0, import_react50.useMemo)(() => {
89177
+ const suggestion = (0, import_react52.useMemo)(() => {
88973
89178
  if (state.value.length === 0) {
88974
89179
  return;
88975
89180
  }
88976
89181
  return suggestions?.find((suggestion2) => suggestion2.startsWith(state.value))?.replace(state.value, "");
88977
89182
  }, [state.value, suggestions]);
88978
- const moveCursorLeft = (0, import_react50.useCallback)(() => {
89183
+ const moveCursorLeft = (0, import_react52.useCallback)(() => {
88979
89184
  dispatch({
88980
89185
  type: "move-cursor-left"
88981
89186
  });
88982
89187
  }, []);
88983
- const moveCursorRight = (0, import_react50.useCallback)(() => {
89188
+ const moveCursorRight = (0, import_react52.useCallback)(() => {
88984
89189
  dispatch({
88985
89190
  type: "move-cursor-right"
88986
89191
  });
88987
89192
  }, []);
88988
- const insert3 = (0, import_react50.useCallback)((text) => {
89193
+ const insert3 = (0, import_react52.useCallback)((text) => {
88989
89194
  dispatch({
88990
89195
  type: "insert",
88991
89196
  text
88992
89197
  });
88993
89198
  }, []);
88994
- const deleteCharacter = (0, import_react50.useCallback)(() => {
89199
+ const deleteCharacter = (0, import_react52.useCallback)(() => {
88995
89200
  dispatch({
88996
89201
  type: "delete"
88997
89202
  });
88998
89203
  }, []);
88999
- const submit = (0, import_react50.useCallback)(() => {
89204
+ const submit = (0, import_react52.useCallback)(() => {
89000
89205
  if (suggestion) {
89001
89206
  insert3(suggestion);
89002
89207
  onSubmit?.(state.value + suggestion);
@@ -89004,7 +89209,7 @@ var useTextInputState = ({ defaultValue = "", suggestions, onChange, onSubmit })
89004
89209
  }
89005
89210
  onSubmit?.(state.value);
89006
89211
  }, [state.value, suggestion, insert3, onSubmit]);
89007
- (0, import_react50.useEffect)(() => {
89212
+ (0, import_react52.useEffect)(() => {
89008
89213
  if (state.value !== state.previousValue) {
89009
89214
  onChange?.(state.value);
89010
89215
  }
@@ -89021,16 +89226,16 @@ var useTextInputState = ({ defaultValue = "", suggestions, onChange, onSubmit })
89021
89226
  };
89022
89227
 
89023
89228
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/text-input/use-text-input.js
89024
- var import_react51 = __toESM(require_react(), 1);
89229
+ var import_react53 = __toESM(require_react(), 1);
89025
89230
  var cursor = source_default.inverse(" ");
89026
89231
  var useTextInput = ({ isDisabled: isDisabled2 = false, state, placeholder = "" }) => {
89027
- const renderedPlaceholder = (0, import_react51.useMemo)(() => {
89232
+ const renderedPlaceholder = (0, import_react53.useMemo)(() => {
89028
89233
  if (isDisabled2) {
89029
89234
  return placeholder ? source_default.dim(placeholder) : "";
89030
89235
  }
89031
89236
  return placeholder && placeholder.length > 0 ? source_default.inverse(placeholder[0]) + source_default.dim(placeholder.slice(1)) : cursor;
89032
89237
  }, [isDisabled2, placeholder]);
89033
- const renderedValue = (0, import_react51.useMemo)(() => {
89238
+ const renderedValue = (0, import_react53.useMemo)(() => {
89034
89239
  if (isDisabled2) {
89035
89240
  return state.value;
89036
89241
  }
@@ -89090,63 +89295,63 @@ function TextInput({ isDisabled: isDisabled2 = false, defaultValue, placeholder
89090
89295
  state
89091
89296
  });
89092
89297
  const { styles: styles5 } = useComponentTheme("TextInput");
89093
- return import_react52.default.createElement(Text, { ...styles5.value() }, inputValue);
89298
+ return import_react54.default.createElement(Text, { ...styles5.value() }, inputValue);
89094
89299
  }
89095
89300
 
89096
89301
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list.js
89097
- var import_react56 = __toESM(require_react(), 1);
89302
+ var import_react58 = __toESM(require_react(), 1);
89098
89303
 
89099
89304
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list-item.js
89100
- var import_react54 = __toESM(require_react(), 1);
89305
+ var import_react56 = __toESM(require_react(), 1);
89101
89306
 
89102
89307
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list-item-context.js
89103
- var import_react53 = __toESM(require_react(), 1);
89104
- var OrderedListItemContext = (0, import_react53.createContext)({
89308
+ var import_react55 = __toESM(require_react(), 1);
89309
+ var OrderedListItemContext = (0, import_react55.createContext)({
89105
89310
  marker: figures_default.line
89106
89311
  });
89107
89312
 
89108
89313
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list-item.js
89109
89314
  function OrderedListItem({ children }) {
89110
- const { marker } = (0, import_react54.useContext)(OrderedListItemContext);
89315
+ const { marker } = (0, import_react56.useContext)(OrderedListItemContext);
89111
89316
  const { styles: styles5 } = useComponentTheme("OrderedList");
89112
- return import_react54.default.createElement(
89317
+ return import_react56.default.createElement(
89113
89318
  Box_default,
89114
89319
  { ...styles5.listItem() },
89115
- import_react54.default.createElement(Text, { ...styles5.marker() }, marker),
89116
- import_react54.default.createElement(Box_default, { ...styles5.content() }, children)
89320
+ import_react56.default.createElement(Text, { ...styles5.marker() }, marker),
89321
+ import_react56.default.createElement(Box_default, { ...styles5.content() }, children)
89117
89322
  );
89118
89323
  }
89119
89324
 
89120
89325
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list-context.js
89121
- var import_react55 = __toESM(require_react(), 1);
89122
- var OrderedListContext = (0, import_react55.createContext)({
89326
+ var import_react57 = __toESM(require_react(), 1);
89327
+ var OrderedListContext = (0, import_react57.createContext)({
89123
89328
  marker: ""
89124
89329
  });
89125
89330
 
89126
89331
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/ordered-list/ordered-list.js
89127
89332
  function OrderedList({ children }) {
89128
- const { marker: parentMarker } = (0, import_react56.useContext)(OrderedListContext);
89333
+ const { marker: parentMarker } = (0, import_react58.useContext)(OrderedListContext);
89129
89334
  const { styles: styles5 } = useComponentTheme("OrderedList");
89130
89335
  let numberOfItems = 0;
89131
- for (const child of import_react56.default.Children.toArray(children)) {
89132
- if (!(0, import_react56.isValidElement)(child) || child.type !== OrderedListItem) {
89336
+ for (const child of import_react58.default.Children.toArray(children)) {
89337
+ if (!(0, import_react58.isValidElement)(child) || child.type !== OrderedListItem) {
89133
89338
  continue;
89134
89339
  }
89135
89340
  numberOfItems++;
89136
89341
  }
89137
89342
  const maxMarkerWidth = String(numberOfItems).length;
89138
- return import_react56.default.createElement(Box_default, { ...styles5.list() }, import_react56.default.Children.map(children, (child, index) => {
89139
- if (!(0, import_react56.isValidElement)(child) || child.type !== OrderedListItem) {
89343
+ return import_react58.default.createElement(Box_default, { ...styles5.list() }, import_react58.default.Children.map(children, (child, index) => {
89344
+ if (!(0, import_react58.isValidElement)(child) || child.type !== OrderedListItem) {
89140
89345
  return child;
89141
89346
  }
89142
89347
  const paddedMarker = `${String(index + 1).padStart(maxMarkerWidth)}.`;
89143
89348
  const marker = `${parentMarker}${paddedMarker}`;
89144
89349
  return (
89145
89350
  // eslint-disable-next-line react/jsx-no-constructed-context-values
89146
- import_react56.default.createElement(
89351
+ import_react58.default.createElement(
89147
89352
  OrderedListContext.Provider,
89148
89353
  { value: { marker } },
89149
- import_react56.default.createElement(OrderedListItemContext.Provider, { value: { marker } }, child)
89354
+ import_react58.default.createElement(OrderedListItemContext.Provider, { value: { marker } }, child)
89150
89355
  )
89151
89356
  );
89152
89357
  }));
@@ -89154,34 +89359,34 @@ function OrderedList({ children }) {
89154
89359
  OrderedList.Item = OrderedListItem;
89155
89360
 
89156
89361
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/password-input/password-input.js
89157
- var import_react59 = __toESM(require_react(), 1);
89362
+ var import_react61 = __toESM(require_react(), 1);
89158
89363
 
89159
89364
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/password-input/use-password-input-state.js
89160
- var import_react57 = __toESM(require_react(), 1);
89365
+ var import_react59 = __toESM(require_react(), 1);
89161
89366
 
89162
89367
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/password-input/use-password-input.js
89163
- var import_react58 = __toESM(require_react(), 1);
89368
+ var import_react60 = __toESM(require_react(), 1);
89164
89369
  var cursor2 = source_default.inverse(" ");
89165
89370
 
89166
89371
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/status-message/status-message.js
89167
- var import_react60 = __toESM(require_react(), 1);
89372
+ var import_react62 = __toESM(require_react(), 1);
89168
89373
 
89169
89374
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/alert/alert.js
89170
- var import_react61 = __toESM(require_react(), 1);
89375
+ var import_react63 = __toESM(require_react(), 1);
89171
89376
 
89172
89377
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/email-input/email-input.js
89173
- var import_react64 = __toESM(require_react(), 1);
89378
+ var import_react66 = __toESM(require_react(), 1);
89174
89379
 
89175
89380
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/email-input/use-email-input-state.js
89176
- var import_react62 = __toESM(require_react(), 1);
89381
+ var import_react64 = __toESM(require_react(), 1);
89177
89382
 
89178
89383
  // node_modules/.pnpm/@inkjs+ui@2.0.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4_/node_modules/@inkjs/ui/build/components/email-input/use-email-input.js
89179
- var import_react63 = __toESM(require_react(), 1);
89384
+ var import_react65 = __toESM(require_react(), 1);
89180
89385
  var cursor3 = source_default.inverse(" ");
89181
89386
 
89182
89387
  // src/hooks/useInputFocus.tsx
89183
- var import_react65 = __toESM(require_react(), 1);
89184
- var InputFocusContext = (0, import_react65.createContext)({
89388
+ var import_react67 = __toESM(require_react(), 1);
89389
+ var InputFocusContext = (0, import_react67.createContext)({
89185
89390
  isInputActive: false,
89186
89391
  setInputActive: () => {
89187
89392
  }
@@ -89189,137 +89394,20 @@ var InputFocusContext = (0, import_react65.createContext)({
89189
89394
  function InputFocusProvider({
89190
89395
  children
89191
89396
  }) {
89192
- const [isInputActive, setIsInputActive] = (0, import_react65.useState)(false);
89193
- const setInputActive = (0, import_react65.useCallback)((active2) => {
89397
+ const [isInputActive, setIsInputActive] = (0, import_react67.useState)(false);
89398
+ const setInputActive = (0, import_react67.useCallback)((active2) => {
89194
89399
  setIsInputActive(active2);
89195
89400
  }, []);
89196
- return import_react65.default.createElement(
89401
+ return import_react67.default.createElement(
89197
89402
  InputFocusContext.Provider,
89198
89403
  { value: { isInputActive, setInputActive } },
89199
89404
  children
89200
89405
  );
89201
89406
  }
89202
89407
  function useInputFocus() {
89203
- return (0, import_react65.useContext)(InputFocusContext);
89408
+ return (0, import_react67.useContext)(InputFocusContext);
89204
89409
  }
89205
89410
 
89206
- // src/components/layout/TokenInputModal.tsx
89207
- var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
89208
- function TokenInputModal({
89209
- onSubmit,
89210
- error
89211
- }) {
89212
- const theme14 = useTheme();
89213
- const { setInputActive } = useInputFocus();
89214
- const [value5, setValue] = (0, import_react66.useState)("");
89215
- (0, import_react66.useEffect)(() => {
89216
- setInputActive(true);
89217
- return () => setInputActive(false);
89218
- }, [setInputActive]);
89219
- const handleSubmit = () => {
89220
- const trimmed2 = value5.trim();
89221
- if (trimmed2) {
89222
- onSubmit(trimmed2);
89223
- }
89224
- };
89225
- use_input_default((_input, key) => {
89226
- if (key.return) {
89227
- handleSubmit();
89228
- }
89229
- });
89230
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Modal, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
89231
- Box_default,
89232
- {
89233
- flexDirection: "column",
89234
- borderStyle: "round",
89235
- borderColor: theme14.colors.accent,
89236
- backgroundColor: theme14.colors.bg,
89237
- paddingX: 2,
89238
- paddingY: 1,
89239
- gap: 1,
89240
- children: [
89241
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.accent, bold: true, children: "GitHub Token Required" }),
89242
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
89243
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.text, children: "No GitHub token found in your environment." }),
89244
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, children: "Please enter your GitHub Personal Access Token:" })
89245
- ] }),
89246
- error && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.error, children: [
89247
- "Error: ",
89248
- error
89249
- ] }),
89250
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
89251
- Box_default,
89252
- {
89253
- borderStyle: "single",
89254
- borderColor: theme14.colors.border,
89255
- paddingX: 1,
89256
- width: 50,
89257
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextInput, { defaultValue: value5, onChange: setValue })
89258
- }
89259
- ),
89260
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
89261
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, dimColor: true, children: "The token will be saved to ~/.config/lazyreview/.token" }),
89262
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, dimColor: true, children: "Press Enter to submit, Ctrl+C to quit." })
89263
- ] }),
89264
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
89265
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.info, children: "Get a token at: github.com/settings/tokens" }),
89266
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, children: "Required scopes: repo, read:user" })
89267
- ] })
89268
- ]
89269
- }
89270
- ) });
89271
- }
89272
-
89273
- // src/components/common/ErrorBoundary.tsx
89274
- var import_react67 = __toESM(require_react(), 1);
89275
- var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
89276
- function ErrorFallback({ error, onRetry }) {
89277
- const { exit: exit4 } = use_app_default();
89278
- use_input_default((input) => {
89279
- if (input === "q") {
89280
- exit4();
89281
- } else if (input === "R") {
89282
- onRetry();
89283
- }
89284
- });
89285
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
89286
- Box_default,
89287
- {
89288
- flexDirection: "column",
89289
- paddingX: 2,
89290
- paddingY: 1,
89291
- borderStyle: "round",
89292
- borderColor: "red",
89293
- children: [
89294
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: "red", bold: true, children: "Something went wrong" }),
89295
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: "white", children: error.message }) }),
89296
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: "Press q to quit or R to retry" }) })
89297
- ]
89298
- }
89299
- );
89300
- }
89301
- var ErrorBoundary2 = class extends import_react67.default.Component {
89302
- constructor(props) {
89303
- super(props);
89304
- this.state = { error: null };
89305
- }
89306
- static getDerivedStateFromError(error) {
89307
- return { error };
89308
- }
89309
- handleRetry = () => {
89310
- this.setState({ error: null });
89311
- };
89312
- render() {
89313
- if (this.state.error) {
89314
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ErrorFallback, { error: this.state.error, onRetry: this.handleRetry });
89315
- }
89316
- return this.props.children;
89317
- }
89318
- };
89319
-
89320
- // src/screens/PRDetailScreen.tsx
89321
- var import_react88 = __toESM(require_react(), 1);
89322
-
89323
89411
  // node_modules/.pnpm/effect@3.19.16/node_modules/effect/dist/esm/Function.js
89324
89412
  var isFunction = (input) => typeof input === "function";
89325
89413
  var dual = function(arity, body) {
@@ -116720,9 +116808,12 @@ var ArrayFormatterIssue = class extends (/* @__PURE__ */ Struct({
116720
116808
  })) {
116721
116809
  };
116722
116810
 
116723
- // src/services/GitHubApiTypes.ts
116724
- var GitHubApi = class extends Context_exports.Tag("GitHubApi")() {
116725
- };
116811
+ // src/services/Auth.ts
116812
+ import { execFile } from "child_process";
116813
+ import { promisify } from "util";
116814
+ import { writeFile, readFile, mkdir, unlink } from "fs/promises";
116815
+ import { homedir } from "os";
116816
+ import { join as join3 } from "path";
116726
116817
 
116727
116818
  // src/models/errors.ts
116728
116819
  var GitHubError = class extends Data_exports.TaggedError("GitHubError") {
@@ -116744,6 +116835,469 @@ var User = class extends Schema_exports.Class("User")({
116744
116835
  }) {
116745
116836
  };
116746
116837
 
116838
+ // src/services/Auth.ts
116839
+ var execFileAsync = promisify(execFile);
116840
+ var CONFIG_DIR = join3(homedir(), ".config", "lazyreview");
116841
+ var TOKEN_FILE = join3(CONFIG_DIR, ".token");
116842
+ var sessionToken = null;
116843
+ var preferredSource = null;
116844
+ var currentProvider = "github";
116845
+ async function loadSavedToken() {
116846
+ try {
116847
+ const token = await readFile(TOKEN_FILE, "utf-8");
116848
+ return token.trim() || null;
116849
+ } catch {
116850
+ return null;
116851
+ }
116852
+ }
116853
+ async function saveTokenToFile(token) {
116854
+ await mkdir(CONFIG_DIR, { recursive: true });
116855
+ await writeFile(TOKEN_FILE, token, { mode: 384 });
116856
+ }
116857
+ async function deleteSavedToken() {
116858
+ try {
116859
+ await unlink(TOKEN_FILE);
116860
+ } catch {
116861
+ }
116862
+ }
116863
+ var savedToken = null;
116864
+ loadSavedToken().then((token) => {
116865
+ savedToken = token;
116866
+ });
116867
+ function maskToken(token) {
116868
+ if (token.length <= 8) return "****";
116869
+ return `${token.slice(0, 4)}...${token.slice(-4)}`;
116870
+ }
116871
+ async function tryGetGhToken() {
116872
+ try {
116873
+ const { stdout } = await execFileAsync("gh", ["auth", "token"]);
116874
+ return stdout.trim() || null;
116875
+ } catch {
116876
+ return null;
116877
+ }
116878
+ }
116879
+ async function tryGetGlabToken() {
116880
+ try {
116881
+ const { stdout } = await execFileAsync("glab", ["auth", "token"]);
116882
+ return stdout.trim() || null;
116883
+ } catch {
116884
+ return null;
116885
+ }
116886
+ }
116887
+ function getEnvVarName(provider) {
116888
+ return provider === "gitlab" ? "LAZYREVIEW_GITLAB_TOKEN" : "LAZYREVIEW_GITHUB_TOKEN";
116889
+ }
116890
+ function getAuthProvider() {
116891
+ return currentProvider;
116892
+ }
116893
+ var Auth = class extends Context_exports.Tag("Auth")() {
116894
+ };
116895
+ function resolveGitHubToken() {
116896
+ return Effect_exports.gen(function* () {
116897
+ if (preferredSource === "manual") {
116898
+ const manualToken2 = sessionToken ?? savedToken;
116899
+ if (manualToken2) return manualToken2;
116900
+ return yield* Effect_exports.fail(
116901
+ new AuthError({ message: "No manual token found", reason: "no_token" })
116902
+ );
116903
+ }
116904
+ if (preferredSource === "env") {
116905
+ const envToken2 = process.env["LAZYREVIEW_GITHUB_TOKEN"];
116906
+ if (envToken2) return envToken2;
116907
+ return yield* Effect_exports.fail(
116908
+ new AuthError({ message: "LAZYREVIEW_GITHUB_TOKEN not set", reason: "no_token" })
116909
+ );
116910
+ }
116911
+ if (preferredSource === "gh_cli") {
116912
+ const ghToken = yield* Effect_exports.tryPromise({
116913
+ try: tryGetGhToken,
116914
+ catch: () => new AuthError({ message: "gh CLI failed", reason: "no_token" })
116915
+ });
116916
+ if (ghToken) return ghToken;
116917
+ return yield* Effect_exports.fail(
116918
+ new AuthError({ message: "gh CLI token not available", reason: "no_token" })
116919
+ );
116920
+ }
116921
+ const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
116922
+ if (envToken) return envToken;
116923
+ const manualToken = sessionToken ?? savedToken;
116924
+ if (manualToken) return manualToken;
116925
+ const ghResult = yield* Effect_exports.tryPromise({
116926
+ try: tryGetGhToken,
116927
+ catch: () => new AuthError({
116928
+ message: "No GitHub token found. Set LAZYREVIEW_GITHUB_TOKEN or configure in Settings.",
116929
+ reason: "no_token"
116930
+ })
116931
+ });
116932
+ if (ghResult) return ghResult;
116933
+ return yield* Effect_exports.fail(
116934
+ new AuthError({
116935
+ message: "No GitHub token found. Set LAZYREVIEW_GITHUB_TOKEN or configure in Settings.",
116936
+ reason: "no_token"
116937
+ })
116938
+ );
116939
+ });
116940
+ }
116941
+ function resolveGitLabToken() {
116942
+ return Effect_exports.gen(function* () {
116943
+ const envToken = process.env["LAZYREVIEW_GITLAB_TOKEN"];
116944
+ if (envToken) {
116945
+ return yield* Effect_exports.fail(
116946
+ new AuthError({
116947
+ message: "GitLab not yet supported",
116948
+ reason: "no_token"
116949
+ })
116950
+ );
116951
+ }
116952
+ const glabToken = yield* Effect_exports.tryPromise({
116953
+ try: tryGetGlabToken,
116954
+ catch: () => new AuthError({
116955
+ message: "GitLab not yet supported",
116956
+ reason: "no_token"
116957
+ })
116958
+ });
116959
+ if (glabToken) {
116960
+ return yield* Effect_exports.fail(
116961
+ new AuthError({
116962
+ message: "GitLab not yet supported",
116963
+ reason: "no_token"
116964
+ })
116965
+ );
116966
+ }
116967
+ return yield* Effect_exports.fail(
116968
+ new AuthError({
116969
+ message: "GitLab not yet supported",
116970
+ reason: "no_token"
116971
+ })
116972
+ );
116973
+ });
116974
+ }
116975
+ function resolveToken() {
116976
+ return currentProvider === "gitlab" ? resolveGitLabToken() : resolveGitHubToken();
116977
+ }
116978
+ function resolveGitHubTokenInfo() {
116979
+ return Effect_exports.gen(function* () {
116980
+ if (preferredSource === "manual") {
116981
+ const manualToken2 = sessionToken ?? savedToken;
116982
+ if (manualToken2) {
116983
+ return {
116984
+ source: "manual",
116985
+ token: manualToken2,
116986
+ maskedToken: maskToken(manualToken2)
116987
+ };
116988
+ }
116989
+ }
116990
+ if (preferredSource === "env") {
116991
+ const envToken2 = process.env["LAZYREVIEW_GITHUB_TOKEN"];
116992
+ if (envToken2) {
116993
+ return {
116994
+ source: "env",
116995
+ token: envToken2,
116996
+ maskedToken: maskToken(envToken2)
116997
+ };
116998
+ }
116999
+ }
117000
+ if (preferredSource === "gh_cli") {
117001
+ const ghToken2 = yield* Effect_exports.promise(tryGetGhToken);
117002
+ if (ghToken2) {
117003
+ return {
117004
+ source: "gh_cli",
117005
+ token: ghToken2,
117006
+ maskedToken: maskToken(ghToken2)
117007
+ };
117008
+ }
117009
+ }
117010
+ const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117011
+ if (envToken) {
117012
+ return {
117013
+ source: "env",
117014
+ token: envToken,
117015
+ maskedToken: maskToken(envToken)
117016
+ };
117017
+ }
117018
+ const manualToken = sessionToken ?? savedToken;
117019
+ if (manualToken) {
117020
+ return {
117021
+ source: "manual",
117022
+ token: manualToken,
117023
+ maskedToken: maskToken(manualToken)
117024
+ };
117025
+ }
117026
+ const ghToken = yield* Effect_exports.promise(tryGetGhToken);
117027
+ if (ghToken) {
117028
+ return {
117029
+ source: "gh_cli",
117030
+ token: ghToken,
117031
+ maskedToken: maskToken(ghToken)
117032
+ };
117033
+ }
117034
+ return {
117035
+ source: "none",
117036
+ token: null,
117037
+ maskedToken: null
117038
+ };
117039
+ });
117040
+ }
117041
+ function resolveTokenInfo() {
117042
+ if (currentProvider === "gitlab") {
117043
+ return Effect_exports.succeed({
117044
+ source: "none",
117045
+ token: null,
117046
+ maskedToken: null
117047
+ });
117048
+ }
117049
+ return resolveGitHubTokenInfo();
117050
+ }
117051
+ function getGitHubUser(token) {
117052
+ return Effect_exports.tryPromise({
117053
+ try: async () => {
117054
+ const response = await fetch("https://api.github.com/user", {
117055
+ headers: {
117056
+ Authorization: `Bearer ${token}`,
117057
+ Accept: "application/vnd.github+json"
117058
+ }
117059
+ });
117060
+ if (!response.ok) {
117061
+ throw new Error(`GitHub API returned ${response.status}`);
117062
+ }
117063
+ const data = await response.json();
117064
+ return Schema_exports.decodeUnknownSync(User)(data);
117065
+ },
117066
+ catch: (error) => new AuthError({
117067
+ message: `Failed to get user: ${String(error)}`,
117068
+ reason: "invalid_token"
117069
+ })
117070
+ });
117071
+ }
117072
+ function getGitLabUser(_token) {
117073
+ return Effect_exports.fail(
117074
+ new AuthError({
117075
+ message: "GitLab not yet supported",
117076
+ reason: "no_token"
117077
+ })
117078
+ );
117079
+ }
117080
+ function getUser() {
117081
+ return Effect_exports.gen(function* () {
117082
+ const token = yield* resolveToken();
117083
+ return currentProvider === "gitlab" ? yield* getGitLabUser(token) : yield* getGitHubUser(token);
117084
+ });
117085
+ }
117086
+ var AuthLive = Layer_exports.succeed(
117087
+ Auth,
117088
+ Auth.of({
117089
+ getToken: resolveToken,
117090
+ getUser,
117091
+ isAuthenticated: () => Effect_exports.gen(function* () {
117092
+ const result = yield* Effect_exports.either(resolveToken());
117093
+ return result._tag === "Right";
117094
+ }),
117095
+ setToken: (token) => Effect_exports.gen(function* () {
117096
+ sessionToken = token;
117097
+ savedToken = token;
117098
+ preferredSource = "manual";
117099
+ yield* Effect_exports.promise(() => saveTokenToFile(token));
117100
+ }),
117101
+ getTokenInfo: resolveTokenInfo,
117102
+ setPreferredSource: (source) => Effect_exports.sync(() => {
117103
+ preferredSource = source === "none" ? null : source;
117104
+ }),
117105
+ getAvailableSources: () => Effect_exports.gen(function* () {
117106
+ const sources = [];
117107
+ if (currentProvider === "gitlab") {
117108
+ const envToken2 = process.env["LAZYREVIEW_GITLAB_TOKEN"];
117109
+ if (envToken2) {
117110
+ sources.push("env");
117111
+ }
117112
+ const glabToken = yield* Effect_exports.promise(tryGetGlabToken);
117113
+ if (glabToken) {
117114
+ sources.push("gh_cli");
117115
+ }
117116
+ return sources;
117117
+ }
117118
+ const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117119
+ if (envToken) {
117120
+ sources.push("env");
117121
+ }
117122
+ if (sessionToken || savedToken) {
117123
+ sources.push("manual");
117124
+ }
117125
+ const ghToken = yield* Effect_exports.promise(tryGetGhToken);
117126
+ if (ghToken) {
117127
+ sources.push("gh_cli");
117128
+ }
117129
+ return sources;
117130
+ }),
117131
+ clearManualToken: () => Effect_exports.gen(function* () {
117132
+ sessionToken = null;
117133
+ savedToken = null;
117134
+ if (preferredSource === "manual") {
117135
+ preferredSource = null;
117136
+ }
117137
+ yield* Effect_exports.promise(deleteSavedToken);
117138
+ })
117139
+ })
117140
+ );
117141
+
117142
+ // src/components/layout/TokenInputModal.tsx
117143
+ var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
117144
+ function getProviderLabel(provider) {
117145
+ return provider === "gitlab" ? "GitLab" : "GitHub";
117146
+ }
117147
+ function getTokenUrl(provider) {
117148
+ return provider === "gitlab" ? "gitlab.com/-/user_settings/personal_access_tokens" : "github.com/settings/tokens";
117149
+ }
117150
+ function getRequiredScopes(provider) {
117151
+ return provider === "gitlab" ? "api, read_user" : "repo, read:user";
117152
+ }
117153
+ function TokenInputModal({
117154
+ onSubmit,
117155
+ error
117156
+ }) {
117157
+ const theme14 = useTheme();
117158
+ const { setInputActive } = useInputFocus();
117159
+ const [value5, setValue] = (0, import_react68.useState)("");
117160
+ const provider = getAuthProvider();
117161
+ const providerLabel = getProviderLabel(provider);
117162
+ const envVarName = getEnvVarName(provider);
117163
+ (0, import_react68.useEffect)(() => {
117164
+ setInputActive(true);
117165
+ return () => setInputActive(false);
117166
+ }, [setInputActive]);
117167
+ const handleSubmit = () => {
117168
+ const trimmed2 = value5.trim();
117169
+ if (trimmed2) {
117170
+ onSubmit(trimmed2);
117171
+ }
117172
+ };
117173
+ use_input_default((_input, key) => {
117174
+ if (key.return) {
117175
+ handleSubmit();
117176
+ }
117177
+ });
117178
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Modal, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
117179
+ Box_default,
117180
+ {
117181
+ flexDirection: "column",
117182
+ borderStyle: "round",
117183
+ borderColor: theme14.colors.accent,
117184
+ backgroundColor: theme14.colors.bg,
117185
+ paddingX: 2,
117186
+ paddingY: 1,
117187
+ gap: 1,
117188
+ children: [
117189
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.accent, bold: true, children: [
117190
+ providerLabel,
117191
+ " Token Required"
117192
+ ] }),
117193
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
117194
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.text, children: [
117195
+ "No ",
117196
+ providerLabel,
117197
+ " token found in your environment."
117198
+ ] }),
117199
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.muted, children: [
117200
+ "Please enter your ",
117201
+ providerLabel,
117202
+ " Personal Access Token:"
117203
+ ] })
117204
+ ] }),
117205
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.muted, dimColor: true, children: [
117206
+ "You can also set ",
117207
+ envVarName,
117208
+ " in your environment."
117209
+ ] }) }),
117210
+ error && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.error, children: [
117211
+ "Error: ",
117212
+ error
117213
+ ] }),
117214
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
117215
+ Box_default,
117216
+ {
117217
+ borderStyle: "single",
117218
+ borderColor: theme14.colors.border,
117219
+ paddingX: 1,
117220
+ width: 50,
117221
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextInput, { defaultValue: value5, onChange: setValue })
117222
+ }
117223
+ ),
117224
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
117225
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, dimColor: true, children: "The token will be saved to ~/.config/lazyreview/.token" }),
117226
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: theme14.colors.muted, dimColor: true, children: "Press Enter to submit, Ctrl+C to quit." })
117227
+ ] }),
117228
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
117229
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.info, children: [
117230
+ "Get a token at: ",
117231
+ getTokenUrl(provider)
117232
+ ] }),
117233
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: theme14.colors.muted, children: [
117234
+ "Required scopes: ",
117235
+ getRequiredScopes(provider)
117236
+ ] })
117237
+ ] })
117238
+ ]
117239
+ }
117240
+ ) });
117241
+ }
117242
+
117243
+ // src/components/common/ErrorBoundary.tsx
117244
+ var import_react69 = __toESM(require_react(), 1);
117245
+ var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
117246
+ function ErrorFallback({ error, onRetry }) {
117247
+ const { exit: exit4 } = use_app_default();
117248
+ use_input_default((input) => {
117249
+ if (input === "q") {
117250
+ exit4();
117251
+ } else if (input === "R") {
117252
+ onRetry();
117253
+ }
117254
+ });
117255
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
117256
+ Box_default,
117257
+ {
117258
+ flexDirection: "column",
117259
+ paddingX: 2,
117260
+ paddingY: 1,
117261
+ borderStyle: "round",
117262
+ borderColor: "red",
117263
+ children: [
117264
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: "red", bold: true, children: "Something went wrong" }),
117265
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { color: "white", children: error.message }) }),
117266
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: "Press q to quit or R to retry" }) })
117267
+ ]
117268
+ }
117269
+ );
117270
+ }
117271
+ var ErrorBoundary2 = class extends import_react69.default.Component {
117272
+ constructor(props) {
117273
+ super(props);
117274
+ this.state = { error: null };
117275
+ }
117276
+ static getDerivedStateFromError(error) {
117277
+ return { error };
117278
+ }
117279
+ handleRetry = () => {
117280
+ this.setState({ error: null });
117281
+ };
117282
+ render() {
117283
+ if (this.state.error) {
117284
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ErrorFallback, { error: this.state.error, onRetry: this.handleRetry });
117285
+ }
117286
+ return this.props.children;
117287
+ }
117288
+ };
117289
+
117290
+ // src/screens/PRDetailScreen.tsx
117291
+ var import_react90 = __toESM(require_react(), 1);
117292
+
117293
+ // src/services/GitHubApiTypes.ts
117294
+ var GitHubApi = class extends Context_exports.Tag("GitHubApi")() {
117295
+ };
117296
+
117297
+ // src/services/CodeReviewApiTypes.ts
117298
+ var CodeReviewApi = class extends Context_exports.Tag("CodeReviewApi")() {
117299
+ };
117300
+
116747
117301
  // src/models/pull-request.ts
116748
117302
  var Label = class extends Schema_exports.Class("Label")({
116749
117303
  id: Schema_exports.Number,
@@ -117211,229 +117765,6 @@ function summarizeChecks(checkRuns) {
117211
117765
  return { conclusion, passed, failed, pending: pending3, total };
117212
117766
  }
117213
117767
 
117214
- // src/services/Auth.ts
117215
- import { execFile } from "child_process";
117216
- import { promisify } from "util";
117217
- import { writeFile, readFile, mkdir, unlink } from "fs/promises";
117218
- import { homedir } from "os";
117219
- import { join as join3 } from "path";
117220
- var execFileAsync = promisify(execFile);
117221
- var CONFIG_DIR = join3(homedir(), ".config", "lazyreview");
117222
- var TOKEN_FILE = join3(CONFIG_DIR, ".token");
117223
- var sessionToken = null;
117224
- var preferredSource = null;
117225
- async function loadSavedToken() {
117226
- try {
117227
- const token = await readFile(TOKEN_FILE, "utf-8");
117228
- return token.trim() || null;
117229
- } catch {
117230
- return null;
117231
- }
117232
- }
117233
- async function saveTokenToFile(token) {
117234
- await mkdir(CONFIG_DIR, { recursive: true });
117235
- await writeFile(TOKEN_FILE, token, { mode: 384 });
117236
- }
117237
- async function deleteSavedToken() {
117238
- try {
117239
- await unlink(TOKEN_FILE);
117240
- } catch {
117241
- }
117242
- }
117243
- var savedToken = null;
117244
- loadSavedToken().then((token) => {
117245
- savedToken = token;
117246
- });
117247
- function maskToken(token) {
117248
- if (token.length <= 8) return "****";
117249
- return `${token.slice(0, 4)}...${token.slice(-4)}`;
117250
- }
117251
- async function tryGetGhToken() {
117252
- try {
117253
- const { stdout } = await execFileAsync("gh", ["auth", "token"]);
117254
- return stdout.trim() || null;
117255
- } catch {
117256
- return null;
117257
- }
117258
- }
117259
- var Auth = class extends Context_exports.Tag("Auth")() {
117260
- };
117261
- function resolveToken() {
117262
- return Effect_exports.gen(function* () {
117263
- if (preferredSource === "manual") {
117264
- const manualToken2 = sessionToken ?? savedToken;
117265
- if (manualToken2) return manualToken2;
117266
- return yield* Effect_exports.fail(
117267
- new AuthError({ message: "No manual token found", reason: "no_token" })
117268
- );
117269
- }
117270
- if (preferredSource === "env") {
117271
- const envToken2 = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117272
- if (envToken2) return envToken2;
117273
- return yield* Effect_exports.fail(
117274
- new AuthError({ message: "LAZYREVIEW_GITHUB_TOKEN not set", reason: "no_token" })
117275
- );
117276
- }
117277
- if (preferredSource === "gh_cli") {
117278
- const ghToken = yield* Effect_exports.tryPromise({
117279
- try: tryGetGhToken,
117280
- catch: () => new AuthError({ message: "gh CLI failed", reason: "no_token" })
117281
- });
117282
- if (ghToken) return ghToken;
117283
- return yield* Effect_exports.fail(
117284
- new AuthError({ message: "gh CLI token not available", reason: "no_token" })
117285
- );
117286
- }
117287
- const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117288
- if (envToken) return envToken;
117289
- const manualToken = sessionToken ?? savedToken;
117290
- if (manualToken) return manualToken;
117291
- const ghResult = yield* Effect_exports.tryPromise({
117292
- try: tryGetGhToken,
117293
- catch: () => new AuthError({
117294
- message: "No GitHub token found. Set LAZYREVIEW_GITHUB_TOKEN or configure in Settings.",
117295
- reason: "no_token"
117296
- })
117297
- });
117298
- if (ghResult) return ghResult;
117299
- return yield* Effect_exports.fail(
117300
- new AuthError({
117301
- message: "No GitHub token found. Set LAZYREVIEW_GITHUB_TOKEN or configure in Settings.",
117302
- reason: "no_token"
117303
- })
117304
- );
117305
- });
117306
- }
117307
- function resolveTokenInfo() {
117308
- return Effect_exports.gen(function* () {
117309
- if (preferredSource === "manual") {
117310
- const manualToken2 = sessionToken ?? savedToken;
117311
- if (manualToken2) {
117312
- return {
117313
- source: "manual",
117314
- token: manualToken2,
117315
- maskedToken: maskToken(manualToken2)
117316
- };
117317
- }
117318
- }
117319
- if (preferredSource === "env") {
117320
- const envToken2 = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117321
- if (envToken2) {
117322
- return {
117323
- source: "env",
117324
- token: envToken2,
117325
- maskedToken: maskToken(envToken2)
117326
- };
117327
- }
117328
- }
117329
- if (preferredSource === "gh_cli") {
117330
- const ghToken2 = yield* Effect_exports.promise(tryGetGhToken);
117331
- if (ghToken2) {
117332
- return {
117333
- source: "gh_cli",
117334
- token: ghToken2,
117335
- maskedToken: maskToken(ghToken2)
117336
- };
117337
- }
117338
- }
117339
- const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117340
- if (envToken) {
117341
- return {
117342
- source: "env",
117343
- token: envToken,
117344
- maskedToken: maskToken(envToken)
117345
- };
117346
- }
117347
- const manualToken = sessionToken ?? savedToken;
117348
- if (manualToken) {
117349
- return {
117350
- source: "manual",
117351
- token: manualToken,
117352
- maskedToken: maskToken(manualToken)
117353
- };
117354
- }
117355
- const ghToken = yield* Effect_exports.promise(tryGetGhToken);
117356
- if (ghToken) {
117357
- return {
117358
- source: "gh_cli",
117359
- token: ghToken,
117360
- maskedToken: maskToken(ghToken)
117361
- };
117362
- }
117363
- return {
117364
- source: "none",
117365
- token: null,
117366
- maskedToken: null
117367
- };
117368
- });
117369
- }
117370
- var AuthLive = Layer_exports.succeed(
117371
- Auth,
117372
- Auth.of({
117373
- getToken: resolveToken,
117374
- getUser: () => Effect_exports.gen(function* () {
117375
- const token = yield* resolveToken();
117376
- const user = yield* Effect_exports.tryPromise({
117377
- try: async () => {
117378
- const response = await fetch("https://api.github.com/user", {
117379
- headers: {
117380
- Authorization: `Bearer ${token}`,
117381
- Accept: "application/vnd.github+json"
117382
- }
117383
- });
117384
- if (!response.ok) {
117385
- throw new Error(`GitHub API returned ${response.status}`);
117386
- }
117387
- const data = await response.json();
117388
- return Schema_exports.decodeUnknownSync(User)(data);
117389
- },
117390
- catch: (error) => new AuthError({
117391
- message: `Failed to get user: ${String(error)}`,
117392
- reason: "invalid_token"
117393
- })
117394
- });
117395
- return user;
117396
- }),
117397
- isAuthenticated: () => Effect_exports.gen(function* () {
117398
- const result = yield* Effect_exports.either(resolveToken());
117399
- return result._tag === "Right";
117400
- }),
117401
- setToken: (token) => Effect_exports.gen(function* () {
117402
- sessionToken = token;
117403
- savedToken = token;
117404
- preferredSource = "manual";
117405
- yield* Effect_exports.promise(() => saveTokenToFile(token));
117406
- }),
117407
- getTokenInfo: resolveTokenInfo,
117408
- setPreferredSource: (source) => Effect_exports.sync(() => {
117409
- preferredSource = source === "none" ? null : source;
117410
- }),
117411
- getAvailableSources: () => Effect_exports.gen(function* () {
117412
- const sources = [];
117413
- const envToken = process.env["LAZYREVIEW_GITHUB_TOKEN"];
117414
- if (envToken) {
117415
- sources.push("env");
117416
- }
117417
- if (sessionToken || savedToken) {
117418
- sources.push("manual");
117419
- }
117420
- const ghToken = yield* Effect_exports.promise(tryGetGhToken);
117421
- if (ghToken) {
117422
- sources.push("gh_cli");
117423
- }
117424
- return sources;
117425
- }),
117426
- clearManualToken: () => Effect_exports.gen(function* () {
117427
- sessionToken = null;
117428
- savedToken = null;
117429
- if (preferredSource === "manual") {
117430
- preferredSource = null;
117431
- }
117432
- yield* Effect_exports.promise(deleteSavedToken);
117433
- })
117434
- })
117435
- );
117436
-
117437
117768
  // src/services/GitHubApiLive.ts
117438
117769
  function buildStateQualifier(stateFilter = "open") {
117439
117770
  switch (stateFilter) {
@@ -117446,10 +117777,10 @@ function buildStateQualifier(stateFilter = "open") {
117446
117777
  }
117447
117778
  }
117448
117779
  var GitHubApiLive = Layer_exports.effect(
117449
- GitHubApi,
117780
+ CodeReviewApi,
117450
117781
  Effect_exports.gen(function* () {
117451
117782
  const auth = yield* Auth;
117452
- return GitHubApi.of({
117783
+ return CodeReviewApi.of({
117453
117784
  listPullRequests: (owner, repo, options = {}) => Effect_exports.gen(function* () {
117454
117785
  const token = yield* auth.getToken();
117455
117786
  const mergedOptions = { ...options, perPage: options.perPage ?? 100 };
@@ -117794,10 +118125,14 @@ var KeybindingsSchema = Schema_exports.Struct({
117794
118125
  help: Schema_exports.optionalWith(Schema_exports.String, { default: () => "?" }),
117795
118126
  quit: Schema_exports.optionalWith(Schema_exports.String, { default: () => "q" })
117796
118127
  });
118128
+ var GitLabConfigSchema = Schema_exports.Struct({
118129
+ host: Schema_exports.optionalWith(Schema_exports.String, { default: () => "https://gitlab.com" })
118130
+ });
117797
118131
  var AppConfig = class extends Schema_exports.Class("AppConfig")({
117798
- provider: Schema_exports.optionalWith(Schema_exports.Literal("github"), {
118132
+ provider: Schema_exports.optionalWith(Schema_exports.Union(Schema_exports.Literal("github"), Schema_exports.Literal("gitlab")), {
117799
118133
  default: () => "github"
117800
118134
  }),
118135
+ gitlab: Schema_exports.optional(GitLabConfigSchema),
117801
118136
  theme: Schema_exports.optionalWith(Schema_exports.String, { default: () => "tokyo-night" }),
117802
118137
  defaultOwner: Schema_exports.optional(Schema_exports.String),
117803
118138
  defaultRepo: Schema_exports.optional(Schema_exports.String),
@@ -117853,11 +118188,22 @@ var ConfigLive = Layer_exports.succeed(
117853
118188
  );
117854
118189
 
117855
118190
  // src/services/index.ts
117856
- var GitHubApiFullLive = GitHubApiLive.pipe(Layer_exports.provide(AuthLive));
118191
+ var CodeReviewApiFullLive = GitHubApiLive.pipe(Layer_exports.provide(AuthLive));
118192
+ var GitHubApiCompatLive = Layer_exports.effect(
118193
+ GitHubApi,
118194
+ Effect_exports.gen(function* () {
118195
+ const api = yield* CodeReviewApi;
118196
+ return GitHubApi.of(api);
118197
+ })
118198
+ );
118199
+ var GitHubApiFullCompatLive = GitHubApiCompatLive.pipe(
118200
+ Layer_exports.provide(CodeReviewApiFullLive)
118201
+ );
117857
118202
  var AppLayer = Layer_exports.mergeAll(
117858
118203
  ConfigLive,
117859
118204
  AuthLive,
117860
- GitHubApiFullLive
118205
+ CodeReviewApiFullLive,
118206
+ GitHubApiFullCompatLive
117861
118207
  );
117862
118208
 
117863
118209
  // src/utils/effect.ts
@@ -117927,7 +118273,7 @@ function createGitHubMutation(options) {
117927
118273
  return useMutation({
117928
118274
  mutationFn: (params) => runEffect(
117929
118275
  Effect_exports.gen(function* () {
117930
- const api = yield* GitHubApi;
118276
+ const api = yield* CodeReviewApi;
117931
118277
  return yield* options.effect(api, params);
117932
118278
  })
117933
118279
  ),
@@ -118057,7 +118403,7 @@ function usePullRequests(owner, repo, options) {
118057
118403
  queryKey: ["prs", owner, repo, options],
118058
118404
  queryFn: () => runEffect(
118059
118405
  Effect_exports.gen(function* () {
118060
- const api = yield* GitHubApi;
118406
+ const api = yield* CodeReviewApi;
118061
118407
  return yield* api.listPullRequests(owner, repo, options);
118062
118408
  })
118063
118409
  ),
@@ -118071,7 +118417,7 @@ function usePullRequest(owner, repo, number6) {
118071
118417
  queryKey: ["pr", owner, repo, number6],
118072
118418
  queryFn: () => runEffect(
118073
118419
  Effect_exports.gen(function* () {
118074
- const api = yield* GitHubApi;
118420
+ const api = yield* CodeReviewApi;
118075
118421
  return yield* api.getPullRequest(owner, repo, number6);
118076
118422
  })
118077
118423
  ),
@@ -118085,7 +118431,7 @@ function usePRFiles(owner, repo, number6) {
118085
118431
  queryKey: ["pr-files", owner, repo, number6],
118086
118432
  queryFn: () => runEffect(
118087
118433
  Effect_exports.gen(function* () {
118088
- const api = yield* GitHubApi;
118434
+ const api = yield* CodeReviewApi;
118089
118435
  return yield* api.getPullRequestFiles(owner, repo, number6);
118090
118436
  })
118091
118437
  ),
@@ -118099,7 +118445,7 @@ function usePRComments(owner, repo, number6) {
118099
118445
  queryKey: ["pr-comments", owner, repo, number6],
118100
118446
  queryFn: () => runEffect(
118101
118447
  Effect_exports.gen(function* () {
118102
- const api = yield* GitHubApi;
118448
+ const api = yield* CodeReviewApi;
118103
118449
  return yield* api.getPullRequestComments(owner, repo, number6);
118104
118450
  })
118105
118451
  ),
@@ -118113,7 +118459,7 @@ function useIssueComments(owner, repo, issueNumber) {
118113
118459
  queryKey: ["issue-comments", owner, repo, issueNumber],
118114
118460
  queryFn: () => runEffect(
118115
118461
  Effect_exports.gen(function* () {
118116
- const api = yield* GitHubApi;
118462
+ const api = yield* CodeReviewApi;
118117
118463
  return yield* api.getIssueComments(owner, repo, issueNumber);
118118
118464
  })
118119
118465
  ),
@@ -118128,7 +118474,7 @@ function usePRReviews(owner, repo, number6, options) {
118128
118474
  queryKey: ["pr-reviews", owner, repo, number6],
118129
118475
  queryFn: () => runEffect(
118130
118476
  Effect_exports.gen(function* () {
118131
- const api = yield* GitHubApi;
118477
+ const api = yield* CodeReviewApi;
118132
118478
  return yield* api.getPullRequestReviews(owner, repo, number6);
118133
118479
  })
118134
118480
  ),
@@ -118142,7 +118488,7 @@ function usePRCommits(owner, repo, number6) {
118142
118488
  queryKey: ["pr-commits", owner, repo, number6],
118143
118489
  queryFn: () => runEffect(
118144
118490
  Effect_exports.gen(function* () {
118145
- const api = yield* GitHubApi;
118491
+ const api = yield* CodeReviewApi;
118146
118492
  return yield* api.getPullRequestCommits(owner, repo, number6);
118147
118493
  })
118148
118494
  ),
@@ -118156,7 +118502,7 @@ function useMyPRs(stateFilter = "open") {
118156
118502
  queryKey: ["my-prs", stateFilter],
118157
118503
  queryFn: () => runEffect(
118158
118504
  Effect_exports.gen(function* () {
118159
- const api = yield* GitHubApi;
118505
+ const api = yield* CodeReviewApi;
118160
118506
  return yield* api.getMyPRs(stateFilter);
118161
118507
  })
118162
118508
  ),
@@ -118169,7 +118515,7 @@ function useReviewRequests(stateFilter = "open") {
118169
118515
  queryKey: ["review-requests", stateFilter],
118170
118516
  queryFn: () => runEffect(
118171
118517
  Effect_exports.gen(function* () {
118172
- const api = yield* GitHubApi;
118518
+ const api = yield* CodeReviewApi;
118173
118519
  return yield* api.getReviewRequests(stateFilter);
118174
118520
  })
118175
118521
  ),
@@ -118182,7 +118528,7 @@ function useInvolvedPRs(stateFilter = "open") {
118182
118528
  queryKey: ["involved-prs", stateFilter],
118183
118529
  queryFn: () => runEffect(
118184
118530
  Effect_exports.gen(function* () {
118185
- const api = yield* GitHubApi;
118531
+ const api = yield* CodeReviewApi;
118186
118532
  return yield* api.getInvolvedPRs(stateFilter);
118187
118533
  })
118188
118534
  ),
@@ -118195,7 +118541,7 @@ function useReviewThreads(owner, repo, number6) {
118195
118541
  queryKey: ["pr-review-threads", owner, repo, number6],
118196
118542
  queryFn: () => runEffect(
118197
118543
  Effect_exports.gen(function* () {
118198
- const api = yield* GitHubApi;
118544
+ const api = yield* CodeReviewApi;
118199
118545
  return yield* api.getReviewThreads(owner, repo, number6);
118200
118546
  })
118201
118547
  ),
@@ -118210,7 +118556,7 @@ function useCheckRuns(owner, repo, ref, options) {
118210
118556
  queryKey: ["check-runs", owner, repo, ref],
118211
118557
  queryFn: () => runEffect(
118212
118558
  Effect_exports.gen(function* () {
118213
- const api = yield* GitHubApi;
118559
+ const api = yield* CodeReviewApi;
118214
118560
  return yield* api.getCheckRuns(owner, repo, ref);
118215
118561
  })
118216
118562
  ),
@@ -118223,7 +118569,7 @@ function useCurrentUser() {
118223
118569
  queryKey: ["current-user"],
118224
118570
  queryFn: () => runEffect(
118225
118571
  Effect_exports.gen(function* () {
118226
- const api = yield* GitHubApi;
118572
+ const api = yield* CodeReviewApi;
118227
118573
  return yield* api.getCurrentUser();
118228
118574
  })
118229
118575
  ),
@@ -118232,23 +118578,23 @@ function useCurrentUser() {
118232
118578
  }
118233
118579
 
118234
118580
  // src/hooks/useReviewActions.ts
118235
- var import_react68 = __toESM(require_react(), 1);
118581
+ var import_react70 = __toESM(require_react(), 1);
118236
118582
  function useReviewActions({
118237
118583
  owner,
118238
118584
  repo,
118239
118585
  prNumber,
118240
118586
  setStatusMessage
118241
118587
  }) {
118242
- const [showReviewModal, setShowReviewModal] = (0, import_react68.useState)(false);
118243
- const [reviewError, setReviewError] = (0, import_react68.useState)(null);
118244
- const [showReReviewModal, setShowReReviewModal] = (0, import_react68.useState)(false);
118245
- const [reReviewError, setReReviewError] = (0, import_react68.useState)(null);
118246
- const [showResolved, setShowResolved] = (0, import_react68.useState)(true);
118588
+ const [showReviewModal, setShowReviewModal] = (0, import_react70.useState)(false);
118589
+ const [reviewError, setReviewError] = (0, import_react70.useState)(null);
118590
+ const [showReReviewModal, setShowReReviewModal] = (0, import_react70.useState)(false);
118591
+ const [reReviewError, setReReviewError] = (0, import_react70.useState)(null);
118592
+ const [showResolved, setShowResolved] = (0, import_react70.useState)(true);
118247
118593
  const submitReview = useSubmitReview();
118248
118594
  const resolveThread = useResolveReviewThread();
118249
118595
  const unresolveThread = useUnresolveReviewThread();
118250
118596
  const requestReReview = useRequestReReview();
118251
- const handleReviewSubmit = (0, import_react68.useCallback)(
118597
+ const handleReviewSubmit = (0, import_react70.useCallback)(
118252
118598
  (body, event) => {
118253
118599
  setReviewError(null);
118254
118600
  submitReview.mutate(
@@ -118264,7 +118610,7 @@ function useReviewActions({
118264
118610
  },
118265
118611
  [owner, repo, prNumber, submitReview, setStatusMessage]
118266
118612
  );
118267
- const handleToggleResolve = (0, import_react68.useCallback)(
118613
+ const handleToggleResolve = (0, import_react70.useCallback)(
118268
118614
  (context6) => {
118269
118615
  if (context6.isResolved) {
118270
118616
  unresolveThread.mutate(
@@ -118286,10 +118632,10 @@ function useReviewActions({
118286
118632
  },
118287
118633
  [owner, repo, prNumber, resolveThread, unresolveThread, setStatusMessage]
118288
118634
  );
118289
- const handleToggleShowResolved = (0, import_react68.useCallback)(() => {
118635
+ const handleToggleShowResolved = (0, import_react70.useCallback)(() => {
118290
118636
  setShowResolved((prev) => !prev);
118291
118637
  }, []);
118292
- const handleReReviewSubmit = (0, import_react68.useCallback)(
118638
+ const handleReReviewSubmit = (0, import_react70.useCallback)(
118293
118639
  (reviewers) => {
118294
118640
  setReReviewError(null);
118295
118641
  requestReReview.mutate(
@@ -118305,11 +118651,11 @@ function useReviewActions({
118305
118651
  },
118306
118652
  [owner, repo, prNumber, requestReReview, setStatusMessage]
118307
118653
  );
118308
- const openReviewModal = (0, import_react68.useCallback)(() => {
118654
+ const openReviewModal = (0, import_react70.useCallback)(() => {
118309
118655
  setReviewError(null);
118310
118656
  setShowReviewModal(true);
118311
118657
  }, []);
118312
- const openReReviewModal = (0, import_react68.useCallback)(() => {
118658
+ const openReReviewModal = (0, import_react70.useCallback)(() => {
118313
118659
  setReReviewError(null);
118314
118660
  setShowReReviewModal(true);
118315
118661
  }, []);
@@ -118319,13 +118665,13 @@ function useReviewActions({
118319
118665
  submitReviewPending: submitReview.isPending,
118320
118666
  handleReviewSubmit,
118321
118667
  openReviewModal,
118322
- closeReviewModal: (0, import_react68.useCallback)(() => setShowReviewModal(false), []),
118668
+ closeReviewModal: (0, import_react70.useCallback)(() => setShowReviewModal(false), []),
118323
118669
  showReReviewModal,
118324
118670
  reReviewError,
118325
118671
  requestReReviewPending: requestReReview.isPending,
118326
118672
  handleReReviewSubmit,
118327
118673
  openReReviewModal,
118328
- closeReReviewModal: (0, import_react68.useCallback)(() => setShowReReviewModal(false), []),
118674
+ closeReReviewModal: (0, import_react70.useCallback)(() => setShowReReviewModal(false), []),
118329
118675
  handleToggleResolve,
118330
118676
  showResolved,
118331
118677
  handleToggleShowResolved
@@ -118333,7 +118679,7 @@ function useReviewActions({
118333
118679
  }
118334
118680
 
118335
118681
  // src/hooks/useCommentActions.ts
118336
- var import_react69 = __toESM(require_react(), 1);
118682
+ var import_react71 = __toESM(require_react(), 1);
118337
118683
  function useCommentActions({
118338
118684
  owner,
118339
118685
  repo,
@@ -118341,19 +118687,19 @@ function useCommentActions({
118341
118687
  headSha,
118342
118688
  setStatusMessage
118343
118689
  }) {
118344
- const [showCommentModal, setShowCommentModal] = (0, import_react69.useState)(false);
118345
- const [commentError, setCommentError] = (0, import_react69.useState)(null);
118346
- const [inlineContext, setInlineContext] = (0, import_react69.useState)(null);
118347
- const [replyContext, setReplyContext] = (0, import_react69.useState)(null);
118348
- const [editContext, setEditContext] = (0, import_react69.useState)(null);
118349
- const [descriptionEditContext, setDescriptionEditContext] = (0, import_react69.useState)(null);
118690
+ const [showCommentModal, setShowCommentModal] = (0, import_react71.useState)(false);
118691
+ const [commentError, setCommentError] = (0, import_react71.useState)(null);
118692
+ const [inlineContext, setInlineContext] = (0, import_react71.useState)(null);
118693
+ const [replyContext, setReplyContext] = (0, import_react71.useState)(null);
118694
+ const [editContext, setEditContext] = (0, import_react71.useState)(null);
118695
+ const [descriptionEditContext, setDescriptionEditContext] = (0, import_react71.useState)(null);
118350
118696
  const createComment = useCreateComment();
118351
118697
  const createReviewComment = useCreateReviewComment();
118352
118698
  const replyToReviewComment = useReplyToReviewComment();
118353
118699
  const editIssueComment = useEditIssueComment();
118354
118700
  const editReviewCommentMutation = useEditReviewComment();
118355
118701
  const updatePRDescription = useUpdatePRDescription();
118356
- const handleOpenGeneralComment = (0, import_react69.useCallback)(() => {
118702
+ const handleOpenGeneralComment = (0, import_react71.useCallback)(() => {
118357
118703
  setCommentError(null);
118358
118704
  setInlineContext(null);
118359
118705
  setReplyContext(null);
@@ -118361,7 +118707,7 @@ function useCommentActions({
118361
118707
  setDescriptionEditContext(null);
118362
118708
  setShowCommentModal(true);
118363
118709
  }, []);
118364
- const handleOpenInlineComment = (0, import_react69.useCallback)((context6) => {
118710
+ const handleOpenInlineComment = (0, import_react71.useCallback)((context6) => {
118365
118711
  setCommentError(null);
118366
118712
  setInlineContext(context6);
118367
118713
  setReplyContext(null);
@@ -118369,7 +118715,7 @@ function useCommentActions({
118369
118715
  setDescriptionEditContext(null);
118370
118716
  setShowCommentModal(true);
118371
118717
  }, []);
118372
- const handleOpenReply = (0, import_react69.useCallback)((context6) => {
118718
+ const handleOpenReply = (0, import_react71.useCallback)((context6) => {
118373
118719
  setCommentError(null);
118374
118720
  setInlineContext(null);
118375
118721
  setReplyContext(context6);
@@ -118377,7 +118723,7 @@ function useCommentActions({
118377
118723
  setDescriptionEditContext(null);
118378
118724
  setShowCommentModal(true);
118379
118725
  }, []);
118380
- const handleOpenEditComment = (0, import_react69.useCallback)((context6) => {
118726
+ const handleOpenEditComment = (0, import_react71.useCallback)((context6) => {
118381
118727
  setCommentError(null);
118382
118728
  setInlineContext(null);
118383
118729
  setReplyContext(null);
@@ -118385,7 +118731,7 @@ function useCommentActions({
118385
118731
  setDescriptionEditContext(null);
118386
118732
  setShowCommentModal(true);
118387
118733
  }, []);
118388
- const handleOpenEditDescription = (0, import_react69.useCallback)((context6) => {
118734
+ const handleOpenEditDescription = (0, import_react71.useCallback)((context6) => {
118389
118735
  setCommentError(null);
118390
118736
  setInlineContext(null);
118391
118737
  setReplyContext(null);
@@ -118393,7 +118739,7 @@ function useCommentActions({
118393
118739
  setDescriptionEditContext(context6);
118394
118740
  setShowCommentModal(true);
118395
118741
  }, []);
118396
- const handleEditCommentSubmit = (0, import_react69.useCallback)(
118742
+ const handleEditCommentSubmit = (0, import_react71.useCallback)(
118397
118743
  (body) => {
118398
118744
  if (!editContext) return;
118399
118745
  setCommentError(null);
@@ -118412,7 +118758,7 @@ function useCommentActions({
118412
118758
  },
118413
118759
  [owner, repo, prNumber, editContext, editIssueComment, editReviewCommentMutation, setStatusMessage]
118414
118760
  );
118415
- const handleEditDescriptionSubmit = (0, import_react69.useCallback)(
118761
+ const handleEditDescriptionSubmit = (0, import_react71.useCallback)(
118416
118762
  (body) => {
118417
118763
  if (!descriptionEditContext) return;
118418
118764
  setCommentError(null);
@@ -118430,7 +118776,7 @@ function useCommentActions({
118430
118776
  },
118431
118777
  [owner, repo, prNumber, descriptionEditContext, updatePRDescription, setStatusMessage]
118432
118778
  );
118433
- const handleCommentSubmit = (0, import_react69.useCallback)(
118779
+ const handleCommentSubmit = (0, import_react71.useCallback)(
118434
118780
  (body) => {
118435
118781
  setCommentError(null);
118436
118782
  if (descriptionEditContext) {
@@ -118506,7 +118852,7 @@ function useCommentActions({
118506
118852
  setStatusMessage
118507
118853
  ]
118508
118854
  );
118509
- const closeCommentModal = (0, import_react69.useCallback)(() => {
118855
+ const closeCommentModal = (0, import_react71.useCallback)(() => {
118510
118856
  setShowCommentModal(false);
118511
118857
  setInlineContext(null);
118512
118858
  setReplyContext(null);
@@ -118537,7 +118883,7 @@ function useCommentActions({
118537
118883
  }
118538
118884
 
118539
118885
  // src/hooks/usePRStateActions.ts
118540
- var import_react70 = __toESM(require_react(), 1);
118886
+ var import_react72 = __toESM(require_react(), 1);
118541
118887
  function usePRStateActions({
118542
118888
  owner,
118543
118889
  repo,
@@ -118546,13 +118892,13 @@ function usePRStateActions({
118546
118892
  onMergeSuccess,
118547
118893
  onCloseSuccess
118548
118894
  }) {
118549
- const [showMergeModal, setShowMergeModal] = (0, import_react70.useState)(false);
118550
- const [mergeError, setMergeError] = (0, import_react70.useState)(null);
118551
- const [showCloseConfirm, setShowCloseConfirm] = (0, import_react70.useState)(false);
118895
+ const [showMergeModal, setShowMergeModal] = (0, import_react72.useState)(false);
118896
+ const [mergeError, setMergeError] = (0, import_react72.useState)(null);
118897
+ const [showCloseConfirm, setShowCloseConfirm] = (0, import_react72.useState)(false);
118552
118898
  const mergePR = useMergePR();
118553
118899
  const closePR = useClosePullRequest();
118554
118900
  const reopenPR = useReopenPullRequest();
118555
- const handleMergeSubmit = (0, import_react70.useCallback)(
118901
+ const handleMergeSubmit = (0, import_react72.useCallback)(
118556
118902
  (mergeMethod, commitTitle) => {
118557
118903
  setMergeError(null);
118558
118904
  mergePR.mutate(
@@ -118569,11 +118915,11 @@ function usePRStateActions({
118569
118915
  },
118570
118916
  [owner, repo, prNumber, mergePR, setStatusMessage, onMergeSuccess]
118571
118917
  );
118572
- const openMergeModal = (0, import_react70.useCallback)(() => {
118918
+ const openMergeModal = (0, import_react72.useCallback)(() => {
118573
118919
  setMergeError(null);
118574
118920
  setShowMergeModal(true);
118575
118921
  }, []);
118576
- const handleClosePR = (0, import_react70.useCallback)(() => {
118922
+ const handleClosePR = (0, import_react72.useCallback)(() => {
118577
118923
  closePR.mutate(
118578
118924
  { owner, repo, prNumber },
118579
118925
  {
@@ -118589,7 +118935,7 @@ function usePRStateActions({
118589
118935
  }
118590
118936
  );
118591
118937
  }, [owner, repo, prNumber, closePR, setStatusMessage, onCloseSuccess]);
118592
- const handleReopenPR = (0, import_react70.useCallback)(() => {
118938
+ const handleReopenPR = (0, import_react72.useCallback)(() => {
118593
118939
  reopenPR.mutate(
118594
118940
  { owner, repo, prNumber },
118595
118941
  {
@@ -118604,10 +118950,10 @@ function usePRStateActions({
118604
118950
  mergePRPending: mergePR.isPending,
118605
118951
  handleMergeSubmit,
118606
118952
  openMergeModal,
118607
- closeMergeModal: (0, import_react70.useCallback)(() => setShowMergeModal(false), []),
118953
+ closeMergeModal: (0, import_react72.useCallback)(() => setShowMergeModal(false), []),
118608
118954
  showCloseConfirm,
118609
- openCloseConfirm: (0, import_react70.useCallback)(() => setShowCloseConfirm(true), []),
118610
- closeCloseConfirm: (0, import_react70.useCallback)(() => setShowCloseConfirm(false), []),
118955
+ openCloseConfirm: (0, import_react72.useCallback)(() => setShowCloseConfirm(true), []),
118956
+ closeCloseConfirm: (0, import_react72.useCallback)(() => setShowCloseConfirm(false), []),
118611
118957
  handleClosePR,
118612
118958
  handleReopenPR,
118613
118959
  closePRPending: closePR.isPending,
@@ -118681,22 +119027,22 @@ function usePRDetailModals({
118681
119027
  }
118682
119028
 
118683
119029
  // src/hooks/usePendingReview.ts
118684
- var import_react71 = __toESM(require_react(), 1);
119030
+ var import_react73 = __toESM(require_react(), 1);
118685
119031
  function usePendingReview({
118686
119032
  owner,
118687
119033
  repo,
118688
119034
  prNumber,
118689
119035
  setStatusMessage
118690
119036
  }) {
118691
- const [reviewId, setReviewId] = (0, import_react71.useState)(null);
118692
- const [pendingComments, setPendingComments] = (0, import_react71.useState)([]);
118693
- const [error, setError] = (0, import_react71.useState)(null);
119037
+ const [reviewId, setReviewId] = (0, import_react73.useState)(null);
119038
+ const [pendingComments, setPendingComments] = (0, import_react73.useState)([]);
119039
+ const [error, setError] = (0, import_react73.useState)(null);
118694
119040
  const createPending = useCreatePendingReview();
118695
119041
  const addComment = useAddPendingReviewComment();
118696
119042
  const submitPending = useSubmitPendingReview();
118697
119043
  const discardPending = useDiscardPendingReview();
118698
119044
  const isActive2 = reviewId != null;
118699
- const startReview = (0, import_react71.useCallback)(() => {
119045
+ const startReview = (0, import_react73.useCallback)(() => {
118700
119046
  setError(null);
118701
119047
  createPending.mutate(
118702
119048
  { owner, repo, prNumber },
@@ -118713,7 +119059,7 @@ function usePendingReview({
118713
119059
  }
118714
119060
  );
118715
119061
  }, [owner, repo, prNumber, createPending, setStatusMessage]);
118716
- const addPendingComment = (0, import_react71.useCallback)(
119062
+ const addPendingComment = (0, import_react73.useCallback)(
118717
119063
  (comment, body) => {
118718
119064
  if (reviewId == null) return;
118719
119065
  setError(null);
@@ -118744,7 +119090,7 @@ function usePendingReview({
118744
119090
  },
118745
119091
  [owner, repo, prNumber, reviewId, addComment, pendingComments.length, setStatusMessage]
118746
119092
  );
118747
- const submitReview = (0, import_react71.useCallback)(
119093
+ const submitReview = (0, import_react73.useCallback)(
118748
119094
  (body, event) => {
118749
119095
  if (reviewId == null) return;
118750
119096
  setError(null);
@@ -118765,7 +119111,7 @@ function usePendingReview({
118765
119111
  },
118766
119112
  [owner, repo, prNumber, reviewId, submitPending, setStatusMessage]
118767
119113
  );
118768
- const discardReview = (0, import_react71.useCallback)(() => {
119114
+ const discardReview = (0, import_react73.useCallback)(() => {
118769
119115
  if (reviewId == null) return;
118770
119116
  setError(null);
118771
119117
  discardPending.mutate(
@@ -119845,7 +120191,7 @@ function PRHeader({ pr, owner, repo, prIndex, prTotal }) {
119845
120191
  }
119846
120192
 
119847
120193
  // node_modules/.pnpm/ink-tab@5.2.0_@types+react@19.2.13_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-tab/lib/index.js
119848
- var import_react72 = __toESM(require_react(), 1);
120194
+ var import_react74 = __toESM(require_react(), 1);
119849
120195
  import readline from "readline";
119850
120196
  var _excluded = ["children", "flexDirection", "width", "isFocused", "showIndex", "colors"];
119851
120197
  function _typeof(obj) {
@@ -120023,7 +120369,7 @@ function _toPrimitive(input, hint) {
120023
120369
  }
120024
120370
  var Tab = function Tab2(_ref) {
120025
120371
  var children = _ref.children;
120026
- return /* @__PURE__ */ import_react72.default.createElement(import_react72.default.Fragment, null, children);
120372
+ return /* @__PURE__ */ import_react74.default.createElement(import_react74.default.Fragment, null, children);
120027
120373
  };
120028
120374
  var TabsWithStdin = /* @__PURE__ */ (function(_React$Component) {
120029
120375
  _inherits(TabsWithStdin2, _React$Component);
@@ -120179,7 +120525,7 @@ var TabsWithStdin = /* @__PURE__ */ (function(_React$Component) {
120179
120525
  var activeTab = this.state.activeTab;
120180
120526
  var separatorWidth = width !== null && width !== void 0 ? width : 6;
120181
120527
  var separator = this.isColumn() ? new Array(separatorWidth).fill("\u2500").join("") : " | ";
120182
- return /* @__PURE__ */ import_react72.default.createElement(Box_default, _extends({
120528
+ return /* @__PURE__ */ import_react74.default.createElement(Box_default, _extends({
120183
120529
  flexDirection,
120184
120530
  width
120185
120531
  }, rest), children.map(function(child, key) {
@@ -120197,19 +120543,19 @@ var TabsWithStdin = /* @__PURE__ */ (function(_React$Component) {
120197
120543
  color: activeTab === key ? "black" : void 0
120198
120544
  };
120199
120545
  }
120200
- return /* @__PURE__ */ import_react72.default.createElement(Box_default, {
120546
+ return /* @__PURE__ */ import_react74.default.createElement(Box_default, {
120201
120547
  key: name,
120202
120548
  flexDirection
120203
- }, key !== 0 && /* @__PURE__ */ import_react72.default.createElement(Text, {
120549
+ }, key !== 0 && /* @__PURE__ */ import_react74.default.createElement(Text, {
120204
120550
  color: "dim"
120205
- }, separator), /* @__PURE__ */ import_react72.default.createElement(Box_default, null, showIndex === true && /* @__PURE__ */ import_react72.default.createElement(Text, {
120551
+ }, separator), /* @__PURE__ */ import_react74.default.createElement(Box_default, null, showIndex === true && /* @__PURE__ */ import_react74.default.createElement(Text, {
120206
120552
  color: "grey"
120207
- }, key + 1, ". "), /* @__PURE__ */ import_react72.default.createElement(Text, colors2, child)));
120553
+ }, key + 1, ". "), /* @__PURE__ */ import_react74.default.createElement(Text, colors2, child)));
120208
120554
  }));
120209
120555
  }
120210
120556
  }]);
120211
120557
  return TabsWithStdin2;
120212
- })(import_react72.default.Component);
120558
+ })(import_react74.default.Component);
120213
120559
  _defineProperty(TabsWithStdin, "defaultProps", {
120214
120560
  flexDirection: "row",
120215
120561
  keyMap: null,
@@ -120220,7 +120566,7 @@ _defineProperty(TabsWithStdin, "defaultProps", {
120220
120566
  });
120221
120567
  var Tabs = function Tabs2(props) {
120222
120568
  var _useStdin = use_stdin_default(), isRawModeSupported = _useStdin.isRawModeSupported, stdin = _useStdin.stdin, setRawMode = _useStdin.setRawMode;
120223
- return /* @__PURE__ */ import_react72.default.createElement(TabsWithStdin, _extends({
120569
+ return /* @__PURE__ */ import_react74.default.createElement(TabsWithStdin, _extends({
120224
120570
  isRawModeSupported,
120225
120571
  stdin,
120226
120572
  setRawMode
@@ -120266,14 +120612,14 @@ function PRTabs({ activeIndex, onChange }) {
120266
120612
  }
120267
120613
 
120268
120614
  // src/components/pr/FilesTab.tsx
120269
- var import_react78 = __toESM(require_react(), 1);
120615
+ var import_react80 = __toESM(require_react(), 1);
120270
120616
 
120271
120617
  // node_modules/.pnpm/ink-scroll-list@0.4.1_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-scroll-list/dist/index.js
120272
- var import_react75 = __toESM(require_react(), 1);
120618
+ var import_react77 = __toESM(require_react(), 1);
120273
120619
 
120274
120620
  // node_modules/.pnpm/ink-scroll-view@0.3.5_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-scroll-view/dist/index.js
120275
- var import_react73 = __toESM(require_react(), 1);
120276
- var import_react74 = __toESM(require_react(), 1);
120621
+ var import_react75 = __toESM(require_react(), 1);
120622
+ var import_react76 = __toESM(require_react(), 1);
120277
120623
  var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
120278
120624
  var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
120279
120625
  var MeasurableItem = ({
@@ -120283,8 +120629,8 @@ var MeasurableItem = ({
120283
120629
  width,
120284
120630
  measureKey
120285
120631
  }) => {
120286
- const ref = (0, import_react74.useRef)(null);
120287
- (0, import_react74.useLayoutEffect)(() => {
120632
+ const ref = (0, import_react76.useRef)(null);
120633
+ (0, import_react76.useLayoutEffect)(() => {
120288
120634
  if (ref.current) {
120289
120635
  const { height } = measure_element_default(ref.current);
120290
120636
  onMeasure(index, height);
@@ -120293,17 +120639,17 @@ var MeasurableItem = ({
120293
120639
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Box_default, { ref, flexShrink: 0, width: "100%", flexDirection: "column", children });
120294
120640
  };
120295
120641
  function useStateRef(initialValue) {
120296
- const [state, setStateInternal] = (0, import_react74.useState)(initialValue);
120297
- const ref = (0, import_react74.useRef)(initialValue);
120298
- const setState = (0, import_react74.useCallback)((update5) => {
120642
+ const [state, setStateInternal] = (0, import_react76.useState)(initialValue);
120643
+ const ref = (0, import_react76.useRef)(initialValue);
120644
+ const setState = (0, import_react76.useCallback)((update5) => {
120299
120645
  const nextValue = typeof update5 === "function" ? update5(ref.current) : update5;
120300
120646
  ref.current = nextValue;
120301
120647
  setStateInternal(nextValue);
120302
120648
  }, []);
120303
- const getState = (0, import_react74.useCallback)(() => ref.current, []);
120649
+ const getState = (0, import_react76.useCallback)(() => ref.current, []);
120304
120650
  return [state, setState, getState];
120305
120651
  }
120306
- var ControlledScrollView = (0, import_react74.forwardRef)(
120652
+ var ControlledScrollView = (0, import_react76.forwardRef)(
120307
120653
  ({
120308
120654
  scrollOffset,
120309
120655
  onViewportSizeChange,
@@ -120318,21 +120664,21 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120318
120664
  width: 0
120319
120665
  });
120320
120666
  const [contentHeight, setContentHeight, getContentHeight] = useStateRef(0);
120321
- const [itemMeasureKeys, setItemMeasureKeys] = (0, import_react74.useState)({});
120322
- const viewportRef = (0, import_react74.useRef)(null);
120323
- const contentRef = (0, import_react74.useRef)(null);
120324
- const prevContentHeightRef = (0, import_react74.useRef)(0);
120325
- (0, import_react74.useLayoutEffect)(() => {
120667
+ const [itemMeasureKeys, setItemMeasureKeys] = (0, import_react76.useState)({});
120668
+ const viewportRef = (0, import_react76.useRef)(null);
120669
+ const contentRef = (0, import_react76.useRef)(null);
120670
+ const prevContentHeightRef = (0, import_react76.useRef)(0);
120671
+ (0, import_react76.useLayoutEffect)(() => {
120326
120672
  if (contentHeight !== prevContentHeightRef.current) {
120327
120673
  onContentHeightChange?.(contentHeight, prevContentHeightRef.current);
120328
120674
  prevContentHeightRef.current = contentHeight;
120329
120675
  }
120330
120676
  }, [contentHeight, onContentHeightChange]);
120331
- const itemHeightsRef = (0, import_react74.useRef)({});
120332
- const itemKeysRef = (0, import_react74.useRef)([]);
120333
- const itemOffsetsRef = (0, import_react74.useRef)([]);
120334
- const firstInvalidOffsetIndexRef = (0, import_react74.useRef)(0);
120335
- const handleItemMeasure = (0, import_react74.useCallback)(
120677
+ const itemHeightsRef = (0, import_react76.useRef)({});
120678
+ const itemKeysRef = (0, import_react76.useRef)([]);
120679
+ const itemOffsetsRef = (0, import_react76.useRef)([]);
120680
+ const firstInvalidOffsetIndexRef = (0, import_react76.useRef)(0);
120681
+ const handleItemMeasure = (0, import_react76.useCallback)(
120336
120682
  (index, height) => {
120337
120683
  const key = itemKeysRef.current[index] || index;
120338
120684
  if (itemHeightsRef.current[key] !== height) {
@@ -120363,7 +120709,7 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120363
120709
  setContentHeight
120364
120710
  ]
120365
120711
  );
120366
- const measureViewport = (0, import_react74.useCallback)(() => {
120712
+ const measureViewport = (0, import_react76.useCallback)(() => {
120367
120713
  if (viewportRef.current) {
120368
120714
  const { width, height } = measure_element_default(viewportRef.current);
120369
120715
  const currentSize = getViewportSize();
@@ -120373,17 +120719,17 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120373
120719
  }
120374
120720
  }
120375
120721
  }, [viewportRef, onViewportSizeChange, getViewportSize, setViewportSize]);
120376
- (0, import_react74.useLayoutEffect)(() => {
120722
+ (0, import_react76.useLayoutEffect)(() => {
120377
120723
  measureViewport();
120378
120724
  });
120379
- const prevChildrenRef = (0, import_react74.useRef)(null);
120725
+ const prevChildrenRef = (0, import_react76.useRef)(null);
120380
120726
  if (prevChildrenRef.current !== children) {
120381
120727
  prevChildrenRef.current = children;
120382
120728
  const newItemKeys = [];
120383
120729
  const newItemHeights = {};
120384
- import_react74.Children.forEach(children, (child, index) => {
120730
+ import_react76.Children.forEach(children, (child, index) => {
120385
120731
  if (!child) return;
120386
- const key = (0, import_react74.isValidElement)(child) ? child.key : null;
120732
+ const key = (0, import_react76.isValidElement)(child) ? child.key : null;
120387
120733
  const effectiveKey = key !== null ? key : index;
120388
120734
  newItemKeys[index] = effectiveKey;
120389
120735
  const itemHeight = itemHeightsRef.current[effectiveKey] || 0;
@@ -120402,7 +120748,7 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120402
120748
  setContentHeight(newTotalHeight);
120403
120749
  }
120404
120750
  }
120405
- (0, import_react74.useImperativeHandle)(
120751
+ (0, import_react76.useImperativeHandle)(
120406
120752
  ref,
120407
120753
  () => ({
120408
120754
  getContentHeight,
@@ -120454,7 +120800,7 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120454
120800
  width: "100%",
120455
120801
  flexDirection: "column",
120456
120802
  marginTop: -scrollOffset,
120457
- children: import_react74.Children.map(children, (child, index) => {
120803
+ children: import_react76.Children.map(children, (child, index) => {
120458
120804
  if (!child) return null;
120459
120805
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
120460
120806
  MeasurableItem,
@@ -120465,7 +120811,7 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120465
120811
  measureKey: itemMeasureKeys[index],
120466
120812
  children: child
120467
120813
  },
120468
- (0, import_react74.isValidElement)(child) ? child.key || index : index
120814
+ (0, import_react76.isValidElement)(child) ? child.key || index : index
120469
120815
  );
120470
120816
  })
120471
120817
  }
@@ -120473,17 +120819,17 @@ var ControlledScrollView = (0, import_react74.forwardRef)(
120473
120819
  }
120474
120820
  );
120475
120821
  function useStateRef2(initialValue) {
120476
- const [state, setStateInternal] = (0, import_react73.useState)(initialValue);
120477
- const ref = (0, import_react73.useRef)(initialValue);
120478
- const setState = (0, import_react73.useCallback)((update5) => {
120822
+ const [state, setStateInternal] = (0, import_react75.useState)(initialValue);
120823
+ const ref = (0, import_react75.useRef)(initialValue);
120824
+ const setState = (0, import_react75.useCallback)((update5) => {
120479
120825
  const nextValue = typeof update5 === "function" ? update5(ref.current) : update5;
120480
120826
  ref.current = nextValue;
120481
120827
  setStateInternal(nextValue);
120482
120828
  }, []);
120483
- const getState = (0, import_react73.useCallback)(() => ref.current, []);
120829
+ const getState = (0, import_react75.useCallback)(() => ref.current, []);
120484
120830
  return [state, setState, getState];
120485
120831
  }
120486
- var ScrollView = (0, import_react73.forwardRef)(
120832
+ var ScrollView = (0, import_react75.forwardRef)(
120487
120833
  ({
120488
120834
  onScroll,
120489
120835
  onViewportSizeChange,
@@ -120494,9 +120840,9 @@ var ScrollView = (0, import_react73.forwardRef)(
120494
120840
  ...boxProps
120495
120841
  }, ref) => {
120496
120842
  const [scrollOffset, setScrollOffset, getScrollOffset] = useStateRef2(0);
120497
- const innerRef = (0, import_react73.useRef)(null);
120498
- const contentHeightRef = (0, import_react73.useRef)(0);
120499
- const handleContentHeightChange = (0, import_react73.useCallback)(
120843
+ const innerRef = (0, import_react75.useRef)(null);
120844
+ const contentHeightRef = (0, import_react75.useRef)(0);
120845
+ const handleContentHeightChange = (0, import_react75.useCallback)(
120500
120846
  (height, previousHeight) => {
120501
120847
  contentHeightRef.current = height;
120502
120848
  onContentHeightChange?.(height, previousHeight);
@@ -120507,14 +120853,14 @@ var ScrollView = (0, import_react73.forwardRef)(
120507
120853
  },
120508
120854
  [onContentHeightChange, onScroll, getScrollOffset, setScrollOffset]
120509
120855
  );
120510
- const getBottomOffset = (0, import_react73.useCallback)(
120856
+ const getBottomOffset = (0, import_react75.useCallback)(
120511
120857
  () => Math.max(
120512
120858
  0,
120513
120859
  contentHeightRef.current - (innerRef.current?.getViewportHeight() || 0)
120514
120860
  ),
120515
120861
  []
120516
120862
  );
120517
- (0, import_react73.useImperativeHandle)(
120863
+ (0, import_react75.useImperativeHandle)(
120518
120864
  ref,
120519
120865
  () => ({
120520
120866
  scrollTo: (offset) => {
@@ -120587,7 +120933,7 @@ var ScrollView = (0, import_react73.forwardRef)(
120587
120933
 
120588
120934
  // node_modules/.pnpm/ink-scroll-list@0.4.1_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-scroll-list/dist/index.js
120589
120935
  var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
120590
- var ScrollList = (0, import_react75.forwardRef)(
120936
+ var ScrollList = (0, import_react77.forwardRef)(
120591
120937
  (props, ref) => {
120592
120938
  const {
120593
120939
  children,
@@ -120599,13 +120945,13 @@ var ScrollList = (0, import_react75.forwardRef)(
120599
120945
  onItemHeightChange,
120600
120946
  ...boxProps
120601
120947
  } = props;
120602
- const scrollViewRef = (0, import_react75.useRef)(null);
120603
- const [scrollOffset, setScrollOffset] = (0, import_react75.useState)(0);
120604
- const scrollOffsetRef = (0, import_react75.useRef)(0);
120605
- (0, import_react75.useEffect)(() => {
120948
+ const scrollViewRef = (0, import_react77.useRef)(null);
120949
+ const [scrollOffset, setScrollOffset] = (0, import_react77.useState)(0);
120950
+ const scrollOffsetRef = (0, import_react77.useRef)(0);
120951
+ (0, import_react77.useEffect)(() => {
120606
120952
  scrollOffsetRef.current = scrollOffset;
120607
120953
  }, [scrollOffset]);
120608
- const updateScroll = (0, import_react75.useCallback)(
120954
+ const updateScroll = (0, import_react77.useCallback)(
120609
120955
  (newOffset) => {
120610
120956
  if (newOffset !== scrollOffsetRef.current) {
120611
120957
  setScrollOffset(newOffset);
@@ -120614,9 +120960,9 @@ var ScrollList = (0, import_react75.forwardRef)(
120614
120960
  },
120615
120961
  [onScroll]
120616
120962
  );
120617
- const selectedIndexRef = (0, import_react75.useRef)(selectedIndex);
120963
+ const selectedIndexRef = (0, import_react77.useRef)(selectedIndex);
120618
120964
  selectedIndexRef.current = selectedIndex;
120619
- const getSelectionVisibleBounds = (0, import_react75.useCallback)(() => {
120965
+ const getSelectionVisibleBounds = (0, import_react77.useCallback)(() => {
120620
120966
  const currentSelectedIndex = selectedIndexRef.current;
120621
120967
  if (currentSelectedIndex === void 0 || currentSelectedIndex < 0) {
120622
120968
  return null;
@@ -120638,7 +120984,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120638
120984
  max: Math.min(globalMaxScroll, maxOffset)
120639
120985
  };
120640
120986
  }, []);
120641
- const clampToSelectionBounds = (0, import_react75.useCallback)(
120987
+ const clampToSelectionBounds = (0, import_react77.useCallback)(
120642
120988
  (targetOffset) => {
120643
120989
  const contentHeight = scrollViewRef.current?.getContentHeight() ?? 0;
120644
120990
  const viewportHeight = scrollViewRef.current?.getViewportHeight() ?? 0;
@@ -120658,7 +121004,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120658
121004
  },
120659
121005
  [getSelectionVisibleBounds]
120660
121006
  );
120661
- const getConstrainedScrollOffset = (0, import_react75.useCallback)(
121007
+ const getConstrainedScrollOffset = (0, import_react77.useCallback)(
120662
121008
  (index, currentOffset, mode, viewportHeightOverride) => {
120663
121009
  const position = scrollViewRef.current?.getItemPosition(index);
120664
121010
  if (!position) return currentOffset;
@@ -120695,12 +121041,12 @@ var ScrollList = (0, import_react75.forwardRef)(
120695
121041
  scrollAlignment
120696
121042
  );
120697
121043
  }
120698
- (0, import_react75.useEffect)(() => {
121044
+ (0, import_react77.useEffect)(() => {
120699
121045
  if (renderScrollOffset !== scrollOffset) {
120700
121046
  updateScroll(renderScrollOffset);
120701
121047
  }
120702
121048
  }, [renderScrollOffset, scrollOffset, updateScroll]);
120703
- const scrollToIndex = (0, import_react75.useCallback)(
121049
+ const scrollToIndex = (0, import_react77.useCallback)(
120704
121050
  (index, mode = scrollAlignment, viewportHeightOverride) => {
120705
121051
  const newOffset = getConstrainedScrollOffset(
120706
121052
  index,
@@ -120712,7 +121058,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120712
121058
  },
120713
121059
  [getConstrainedScrollOffset, scrollOffset, scrollAlignment, updateScroll]
120714
121060
  );
120715
- const handleViewportSizeChange = (0, import_react75.useCallback)(
121061
+ const handleViewportSizeChange = (0, import_react77.useCallback)(
120716
121062
  (size10, previousSize) => {
120717
121063
  if (selectedIndexRef.current !== void 0 && selectedIndexRef.current >= 0) {
120718
121064
  const newOffset = getConstrainedScrollOffset(
@@ -120727,7 +121073,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120727
121073
  },
120728
121074
  [onViewportSizeChange, scrollToIndex]
120729
121075
  );
120730
- const handleItemHeightChange = (0, import_react75.useCallback)(
121076
+ const handleItemHeightChange = (0, import_react77.useCallback)(
120731
121077
  (index, height, previousHeight) => {
120732
121078
  const currentSelectedIndex = selectedIndexRef.current;
120733
121079
  if (currentSelectedIndex !== void 0 && currentSelectedIndex >= 0) {
@@ -120757,7 +121103,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120757
121103
  updateScroll
120758
121104
  ]
120759
121105
  );
120760
- const handleContentHeightChange = (0, import_react75.useCallback)(
121106
+ const handleContentHeightChange = (0, import_react77.useCallback)(
120761
121107
  (height, previousHeight) => {
120762
121108
  if (selectedIndexRef.current !== void 0 && selectedIndexRef.current >= 0) {
120763
121109
  scrollToIndex(selectedIndexRef.current);
@@ -120772,7 +121118,7 @@ var ScrollList = (0, import_react75.forwardRef)(
120772
121118
  },
120773
121119
  [onContentHeightChange, scrollToIndex]
120774
121120
  );
120775
- (0, import_react75.useImperativeHandle)(
121121
+ (0, import_react77.useImperativeHandle)(
120776
121122
  ref,
120777
121123
  () => ({
120778
121124
  /**
@@ -120867,30 +121213,30 @@ var ScrollList = (0, import_react75.forwardRef)(
120867
121213
  );
120868
121214
 
120869
121215
  // src/hooks/useListNavigation.ts
120870
- var import_react76 = __toESM(require_react(), 1);
121216
+ var import_react78 = __toESM(require_react(), 1);
120871
121217
  function useListNavigation({
120872
121218
  itemCount,
120873
121219
  viewportHeight,
120874
121220
  isActive: isActive2 = true
120875
121221
  }) {
120876
- const [selectedIndex, setSelectedIndex] = (0, import_react76.useState)(0);
120877
- const gPressedAt = (0, import_react76.useRef)(null);
120878
- const prevItemCount = (0, import_react76.useRef)(itemCount);
120879
- (0, import_react76.useEffect)(() => {
121222
+ const [selectedIndex, setSelectedIndex] = (0, import_react78.useState)(0);
121223
+ const gPressedAt = (0, import_react78.useRef)(null);
121224
+ const prevItemCount = (0, import_react78.useRef)(itemCount);
121225
+ (0, import_react78.useEffect)(() => {
120880
121226
  const wasAtEnd = selectedIndex === prevItemCount.current - 1;
120881
121227
  prevItemCount.current = itemCount;
120882
121228
  if (wasAtEnd && itemCount > 0) {
120883
121229
  setSelectedIndex(itemCount - 1);
120884
121230
  }
120885
121231
  }, [itemCount, selectedIndex]);
120886
- (0, import_react76.useEffect)(() => {
121232
+ (0, import_react78.useEffect)(() => {
120887
121233
  if (itemCount === 0) {
120888
121234
  setSelectedIndex(0);
120889
121235
  } else if (selectedIndex >= itemCount) {
120890
121236
  setSelectedIndex(itemCount - 1);
120891
121237
  }
120892
121238
  }, [itemCount, selectedIndex]);
120893
- const clamp9 = (0, import_react76.useCallback)(
121239
+ const clamp9 = (0, import_react78.useCallback)(
120894
121240
  (index) => Math.max(0, Math.min(index, itemCount - 1)),
120895
121241
  [itemCount]
120896
121242
  );
@@ -120947,10 +121293,61 @@ function deriveScrollOffset(selectedIndex, viewportHeight, itemCount) {
120947
121293
  }
120948
121294
 
120949
121295
  // src/hooks/useViewedFiles.ts
120950
- var import_react77 = __toESM(require_react(), 1);
120951
- import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
121296
+ var import_react79 = __toESM(require_react(), 1);
121297
+ import { readFileSync as readFileSync2 } from "fs";
120952
121298
  import { join as join5 } from "path";
120953
121299
  import { homedir as homedir3 } from "os";
121300
+
121301
+ // src/utils/debouncedWriter.ts
121302
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
121303
+ import { writeFileSync, mkdirSync } from "fs";
121304
+ import { dirname as dirname2 } from "path";
121305
+ var DEBOUNCE_MS = 300;
121306
+ function createDebouncedWriter(filePath) {
121307
+ let timer = null;
121308
+ let pendingData = null;
121309
+ const writeAsync = (data) => {
121310
+ const dir = dirname2(filePath);
121311
+ mkdir3(dir, { recursive: true }).then(() => writeFile3(filePath, JSON.stringify(data, null, 2), "utf-8")).catch(() => {
121312
+ });
121313
+ };
121314
+ const writeSync = (data) => {
121315
+ try {
121316
+ const dir = dirname2(filePath);
121317
+ mkdirSync(dir, { recursive: true });
121318
+ writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
121319
+ } catch {
121320
+ }
121321
+ };
121322
+ const flush = () => {
121323
+ if (timer !== null) {
121324
+ clearTimeout(timer);
121325
+ timer = null;
121326
+ }
121327
+ if (pendingData !== null) {
121328
+ writeSync(pendingData);
121329
+ pendingData = null;
121330
+ }
121331
+ };
121332
+ process.on("exit", flush);
121333
+ const schedule2 = (data) => {
121334
+ pendingData = data;
121335
+ if (timer !== null) {
121336
+ clearTimeout(timer);
121337
+ }
121338
+ timer = setTimeout(() => {
121339
+ timer = null;
121340
+ if (pendingData !== null) {
121341
+ const toWrite = pendingData;
121342
+ pendingData = null;
121343
+ writeAsync(toWrite);
121344
+ }
121345
+ }, DEBOUNCE_MS);
121346
+ };
121347
+ return { schedule: schedule2, flush };
121348
+ }
121349
+
121350
+ // src/hooks/useViewedFiles.ts
120954
121351
  var CONFIG_DIR2 = join5(homedir3(), ".config", "lazyreview");
120955
121352
  var VIEWED_FILES_PATH = join5(CONFIG_DIR2, "viewed-files.json");
120956
121353
  var PRUNE_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -120963,13 +121360,6 @@ function loadFromDisk() {
120963
121360
  return {};
120964
121361
  }
120965
121362
  }
120966
- function saveToDisk(data) {
120967
- try {
120968
- mkdirSync(CONFIG_DIR2, { recursive: true });
120969
- writeFileSync(VIEWED_FILES_PATH, JSON.stringify(data, null, 2), "utf-8");
120970
- } catch {
120971
- }
120972
- }
120973
121363
  function pruneOldEntries(data) {
120974
121364
  const now2 = Date.now();
120975
121365
  const result = {};
@@ -120982,9 +121372,10 @@ function pruneOldEntries(data) {
120982
121372
  return result;
120983
121373
  }
120984
121374
  function createViewedFilesStore() {
121375
+ const writer = createDebouncedWriter(VIEWED_FILES_PATH);
120985
121376
  let data = pruneOldEntries(loadFromDisk());
120986
121377
  let listeners2 = [];
120987
- saveToDisk(data);
121378
+ writer.schedule(data);
120988
121379
  const notify2 = () => {
120989
121380
  listeners2.forEach((l) => l());
120990
121381
  };
@@ -121009,7 +121400,7 @@ function createViewedFilesStore() {
121009
121400
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
121010
121401
  }
121011
121402
  };
121012
- saveToDisk(data);
121403
+ writer.schedule(data);
121013
121404
  notify2();
121014
121405
  },
121015
121406
  markUnviewed(prUrl, filePath) {
@@ -121023,7 +121414,7 @@ function createViewedFilesStore() {
121023
121414
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
121024
121415
  }
121025
121416
  };
121026
- saveToDisk(data);
121417
+ writer.schedule(data);
121027
121418
  notify2();
121028
121419
  },
121029
121420
  toggleViewed(prUrl, filePath) {
@@ -121049,30 +121440,30 @@ function createViewedFilesStore() {
121049
121440
  }
121050
121441
  var store4 = createViewedFilesStore();
121051
121442
  function useViewedFiles() {
121052
- const viewedFilesData = (0, import_react77.useSyncExternalStore)(
121443
+ const viewedFilesData = (0, import_react79.useSyncExternalStore)(
121053
121444
  store4.subscribe,
121054
121445
  store4.getSnapshot,
121055
121446
  () => ({})
121056
121447
  );
121057
- const markViewed = (0, import_react77.useCallback)(
121448
+ const markViewed = (0, import_react79.useCallback)(
121058
121449
  (prUrl, filePath) => {
121059
121450
  store4.markViewed(prUrl, filePath);
121060
121451
  },
121061
121452
  []
121062
121453
  );
121063
- const markUnviewed = (0, import_react77.useCallback)(
121454
+ const markUnviewed = (0, import_react79.useCallback)(
121064
121455
  (prUrl, filePath) => {
121065
121456
  store4.markUnviewed(prUrl, filePath);
121066
121457
  },
121067
121458
  []
121068
121459
  );
121069
- const toggleViewed = (0, import_react77.useCallback)(
121460
+ const toggleViewed = (0, import_react79.useCallback)(
121070
121461
  (prUrl, filePath) => {
121071
121462
  store4.toggleViewed(prUrl, filePath);
121072
121463
  },
121073
121464
  []
121074
121465
  );
121075
- const isViewed = (0, import_react77.useCallback)(
121466
+ const isViewed = (0, import_react79.useCallback)(
121076
121467
  (prUrl, filePath) => {
121077
121468
  return store4.isViewed(prUrl, filePath);
121078
121469
  },
@@ -121080,7 +121471,7 @@ function useViewedFiles() {
121080
121471
  [viewedFilesData]
121081
121472
  // Re-evaluate when data changes
121082
121473
  );
121083
- const getViewedCount = (0, import_react77.useCallback)(
121474
+ const getViewedCount = (0, import_react79.useCallback)(
121084
121475
  (prUrl) => {
121085
121476
  return store4.getViewedCount(prUrl);
121086
121477
  },
@@ -121181,13 +121572,13 @@ function EmptyState({
121181
121572
  }
121182
121573
 
121183
121574
  // node_modules/.pnpm/ink-syntax-highlight@2.0.2_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-syntax-highlight/build/index.js
121184
- var React40 = __toESM(require_react(), 1);
121575
+ var React41 = __toESM(require_react(), 1);
121185
121576
  var import_cli_highlight = __toESM(require_dist2(), 1);
121186
121577
  var SyntaxHighlight = ({ code, language, theme: theme14 }) => {
121187
- const highlightedCode = React40.useMemo(() => {
121578
+ const highlightedCode = React41.useMemo(() => {
121188
121579
  return (0, import_cli_highlight.highlight)(code, { language, theme: theme14 });
121189
121580
  }, [code, language, theme14]);
121190
- return React40.createElement(Text, null, highlightedCode);
121581
+ return React41.createElement(Text, null, highlightedCode);
121191
121582
  };
121192
121583
  var build_default = SyntaxHighlight;
121193
121584
 
@@ -121843,6 +122234,30 @@ function FileItem({
121843
122234
 
121844
122235
  // src/components/pr/FilesTab.tsx
121845
122236
  var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1);
122237
+ function getFocusedCommentThread(effectiveDiffMode, diffSelectedLine, allRows, sideBySideRows) {
122238
+ if (effectiveDiffMode === "side-by-side") {
122239
+ const row2 = sideBySideRows[diffSelectedLine];
122240
+ return row2?.type === "comment" ? row2.thread : void 0;
122241
+ }
122242
+ const row = allRows[diffSelectedLine];
122243
+ return row?.type === "comment" ? row.thread : void 0;
122244
+ }
122245
+ function getFocusedLine(effectiveDiffMode, index, allRows, sideBySideRows) {
122246
+ if (effectiveDiffMode === "side-by-side") {
122247
+ const row2 = sideBySideRows[index];
122248
+ if (!row2 || row2.type === "comment") return void 0;
122249
+ if (row2.type === "header") {
122250
+ if (row2.left) return { line: row2.left, oldLineNumber: row2.left.oldLineNumber, newLineNumber: row2.left.newLineNumber };
122251
+ return void 0;
122252
+ }
122253
+ const activeLine = row2.right ?? row2.left;
122254
+ if (!activeLine) return void 0;
122255
+ return { line: activeLine, oldLineNumber: activeLine.oldLineNumber, newLineNumber: activeLine.newLineNumber };
122256
+ }
122257
+ const row = allRows[index];
122258
+ if (!row || row.type !== "line") return void 0;
122259
+ return { line: row.line, oldLineNumber: row.oldLineNumber, newLineNumber: row.newLineNumber };
122260
+ }
121846
122261
  function fuzzyMatch(filename, query) {
121847
122262
  const lower = filename.toLowerCase();
121848
122263
  const q = query.toLowerCase();
@@ -121869,29 +122284,29 @@ function FilesTab({
121869
122284
  const { setInputActive } = useInputFocus();
121870
122285
  const { markViewed, toggleViewed, isViewed, getViewedCount } = useViewedFiles();
121871
122286
  const viewportHeight = Math.max(1, (stdout?.rows ?? 24) - 13);
121872
- const [focusPanel, setFocusPanel] = (0, import_react78.useState)("tree");
121873
- const [selectedFileIndex, setSelectedFileIndex] = (0, import_react78.useState)(0);
121874
- const [visualStart, setVisualStart] = (0, import_react78.useState)(null);
121875
- const [diffMode, setDiffMode] = (0, import_react78.useState)("unified");
122287
+ const [focusPanel, setFocusPanel] = (0, import_react80.useState)("tree");
122288
+ const [selectedFileIndex, setSelectedFileIndex] = (0, import_react80.useState)(0);
122289
+ const [visualStart, setVisualStart] = (0, import_react80.useState)(null);
122290
+ const [diffMode, setDiffMode] = (0, import_react80.useState)("unified");
121876
122291
  const terminalWidth = stdout?.columns ?? 120;
121877
122292
  const effectiveDiffMode = diffMode === "side-by-side" && terminalWidth < SIDE_BY_SIDE_MIN_WIDTH ? "unified" : diffMode;
121878
- const [isFiltering, setIsFiltering] = (0, import_react78.useState)(false);
121879
- const [filterQuery, setFilterQuery] = (0, import_react78.useState)("");
121880
- const [activeFilter, setActiveFilter] = (0, import_react78.useState)("");
121881
- const filteredFiles = (0, import_react78.useMemo)(() => {
122293
+ const [isFiltering, setIsFiltering] = (0, import_react80.useState)(false);
122294
+ const [filterQuery, setFilterQuery] = (0, import_react80.useState)("");
122295
+ const [activeFilter, setActiveFilter] = (0, import_react80.useState)("");
122296
+ const filteredFiles = (0, import_react80.useMemo)(() => {
121882
122297
  if (!activeFilter && !isFiltering) return files;
121883
122298
  const query = isFiltering ? filterQuery : activeFilter;
121884
122299
  if (!query) return files;
121885
122300
  return files.filter((f) => fuzzyMatch(f.filename, query));
121886
122301
  }, [files, activeFilter, filterQuery, isFiltering]);
121887
- const filteredTree = (0, import_react78.useMemo)(() => buildFileTree(filteredFiles), [filteredFiles]);
121888
- const fileOrder = (0, import_react78.useMemo)(() => flattenTreeToFiles(filteredTree), [filteredTree]);
121889
- const displayRows = (0, import_react78.useMemo)(
122302
+ const filteredTree = (0, import_react80.useMemo)(() => buildFileTree(filteredFiles), [filteredFiles]);
122303
+ const fileOrder = (0, import_react80.useMemo)(() => flattenTreeToFiles(filteredTree), [filteredTree]);
122304
+ const displayRows = (0, import_react80.useMemo)(
121890
122305
  () => buildDisplayRows(filteredTree, 0, { current: 0 }),
121891
122306
  [filteredTree]
121892
122307
  );
121893
122308
  const treeViewportHeight = viewportHeight - 2;
121894
- const fileTreeListRef = (0, import_react78.useRef)(null);
122309
+ const fileTreeListRef = (0, import_react80.useRef)(null);
121895
122310
  const { selectedIndex: treeSelectedIndex } = useListNavigation({
121896
122311
  itemCount: fileOrder.length,
121897
122312
  viewportHeight: treeViewportHeight,
@@ -121901,19 +122316,19 @@ function FilesTab({
121901
122316
  (r) => r.type === "file" && r.fileIndex === treeSelectedIndex
121902
122317
  );
121903
122318
  const effectiveRowIndex = selectedRowIndex >= 0 ? selectedRowIndex : 0;
121904
- (0, import_react78.useEffect)(() => {
122319
+ (0, import_react80.useEffect)(() => {
121905
122320
  const handleResize = () => fileTreeListRef.current?.remeasure();
121906
122321
  stdout?.on("resize", handleResize);
121907
122322
  return () => {
121908
122323
  stdout?.off("resize", handleResize);
121909
122324
  };
121910
122325
  }, [stdout]);
121911
- import_react78.default.useEffect(() => {
122326
+ import_react80.default.useEffect(() => {
121912
122327
  if (focusPanel === "tree") {
121913
122328
  setSelectedFileIndex(treeSelectedIndex);
121914
122329
  }
121915
122330
  }, [treeSelectedIndex, focusPanel]);
121916
- import_react78.default.useEffect(() => {
122331
+ import_react80.default.useEffect(() => {
121917
122332
  const file = fileOrder[selectedFileIndex];
121918
122333
  if (file && prUrl) {
121919
122334
  markViewed(prUrl, file.filename);
@@ -121921,7 +122336,7 @@ function FilesTab({
121921
122336
  }, [selectedFileIndex, fileOrder, prUrl, markViewed]);
121922
122337
  const selectedFile = fileOrder[selectedFileIndex] ?? fileOrder[0] ?? null;
121923
122338
  const hunks = selectedFile?.patch ? parseDiffPatch(selectedFile.patch) : [];
121924
- const commentsByLine = (0, import_react78.useMemo)(() => {
122339
+ const commentsByLine = (0, import_react80.useMemo)(() => {
121925
122340
  if (!comments || comments.length === 0 || !selectedFile) return void 0;
121926
122341
  const fileComments = comments.filter(
121927
122342
  (c) => c.path === selectedFile.filename && c.line != null && c.in_reply_to_id == null
@@ -121952,11 +122367,11 @@ function FilesTab({
121952
122367
  }
121953
122368
  return result;
121954
122369
  }, [comments, reviewThreads, selectedFile]);
121955
- const allRows = (0, import_react78.useMemo)(
122370
+ const allRows = (0, import_react80.useMemo)(
121956
122371
  () => buildDiffRows(hunks, commentsByLine),
121957
122372
  [hunks, commentsByLine]
121958
122373
  );
121959
- const sideBySideRows = (0, import_react78.useMemo)(
122374
+ const sideBySideRows = (0, import_react80.useMemo)(
121960
122375
  () => effectiveDiffMode === "side-by-side" ? buildSideBySideRows(hunks, commentsByLine) : [],
121961
122376
  [hunks, effectiveDiffMode, commentsByLine]
121962
122377
  );
@@ -122019,9 +122434,9 @@ function FilesTab({
122019
122434
  setVisualStart(diffSelectedLine);
122020
122435
  }
122021
122436
  } else if (input === "r" && focusPanel === "diff" && onReply) {
122022
- const focusedRow = allRows[diffSelectedLine];
122023
- if (focusedRow?.type === "comment") {
122024
- const lastComment = focusedRow.thread.comments[focusedRow.thread.comments.length - 1];
122437
+ const thread = getFocusedCommentThread(effectiveDiffMode, diffSelectedLine, allRows, sideBySideRows);
122438
+ if (thread) {
122439
+ const lastComment = thread.comments[thread.comments.length - 1];
122025
122440
  if (lastComment) {
122026
122441
  onReply({
122027
122442
  commentId: lastComment.id,
@@ -122031,17 +122446,17 @@ function FilesTab({
122031
122446
  }
122032
122447
  }
122033
122448
  } else if (input === "x" && focusPanel === "diff" && onToggleResolve) {
122034
- const focusedRow = allRows[diffSelectedLine];
122035
- if (focusedRow?.type === "comment" && focusedRow.thread.threadId) {
122449
+ const thread = getFocusedCommentThread(effectiveDiffMode, diffSelectedLine, allRows, sideBySideRows);
122450
+ if (thread?.threadId) {
122036
122451
  onToggleResolve({
122037
- threadId: focusedRow.thread.threadId,
122038
- isResolved: focusedRow.thread.isResolved ?? false
122452
+ threadId: thread.threadId,
122453
+ isResolved: thread.isResolved ?? false
122039
122454
  });
122040
122455
  }
122041
122456
  } else if (input === "e" && focusPanel === "diff" && onEditComment && currentUser) {
122042
- const focusedRow = allRows[diffSelectedLine];
122043
- if (focusedRow?.type === "comment") {
122044
- const ownComment = focusedRow.thread.comments.find((c) => c.user.login === currentUser);
122457
+ const thread = getFocusedCommentThread(effectiveDiffMode, diffSelectedLine, allRows, sideBySideRows);
122458
+ if (thread) {
122459
+ const ownComment = thread.comments.find((c) => c.user.login === currentUser);
122045
122460
  if (ownComment) {
122046
122461
  onEditComment({
122047
122462
  commentId: ownComment.id,
@@ -122054,13 +122469,13 @@ function FilesTab({
122054
122469
  if (visualStart != null) {
122055
122470
  const selMin = Math.min(visualStart, diffSelectedLine);
122056
122471
  const selMax = Math.max(visualStart, diffSelectedLine);
122057
- const startRow = allRows[selMin];
122058
- const endRow = allRows[selMax];
122059
- if (startRow?.type === "line" && endRow?.type === "line" && startRow.line.type !== "header" && endRow.line.type !== "header") {
122060
- const endSide = endRow.line.type === "del" ? "LEFT" : "RIGHT";
122061
- const startSide = startRow.line.type === "del" ? "LEFT" : "RIGHT";
122062
- const endLine = endSide === "LEFT" ? endRow.oldLineNumber : endRow.newLineNumber;
122063
- const startLine = startSide === "LEFT" ? startRow.oldLineNumber : startRow.newLineNumber;
122472
+ const startInfo = getFocusedLine(effectiveDiffMode, selMin, allRows, sideBySideRows);
122473
+ const endInfo = getFocusedLine(effectiveDiffMode, selMax, allRows, sideBySideRows);
122474
+ if (startInfo && endInfo && startInfo.line.type !== "header" && endInfo.line.type !== "header") {
122475
+ const endSide = endInfo.line.type === "del" ? "LEFT" : "RIGHT";
122476
+ const startSide = startInfo.line.type === "del" ? "LEFT" : "RIGHT";
122477
+ const endLine = endSide === "LEFT" ? endInfo.oldLineNumber : endInfo.newLineNumber;
122478
+ const startLine = startSide === "LEFT" ? startInfo.oldLineNumber : startInfo.newLineNumber;
122064
122479
  if (endLine != null && startLine != null) {
122065
122480
  onInlineComment({
122066
122481
  path: selectedFile.filename,
@@ -122073,10 +122488,10 @@ function FilesTab({
122073
122488
  }
122074
122489
  }
122075
122490
  } else {
122076
- const selectedRow = allRows[diffSelectedLine];
122077
- if (selectedRow?.type === "line" && selectedRow.line.type !== "header") {
122078
- const side = selectedRow.line.type === "del" ? "LEFT" : "RIGHT";
122079
- const line = side === "LEFT" ? selectedRow.oldLineNumber : selectedRow.newLineNumber;
122491
+ const lineInfo = getFocusedLine(effectiveDiffMode, diffSelectedLine, allRows, sideBySideRows);
122492
+ if (lineInfo && lineInfo.line.type !== "header") {
122493
+ const side = lineInfo.line.type === "del" ? "LEFT" : "RIGHT";
122494
+ const line = side === "LEFT" ? lineInfo.oldLineNumber : lineInfo.newLineNumber;
122080
122495
  if (line != null) {
122081
122496
  onInlineComment({
122082
122497
  path: selectedFile.filename,
@@ -122217,7 +122632,7 @@ function FilesTab({
122217
122632
  }
122218
122633
 
122219
122634
  // src/components/pr/ConversationsTab.tsx
122220
- var import_react79 = __toESM(require_react(), 1);
122635
+ var import_react81 = __toESM(require_react(), 1);
122221
122636
 
122222
122637
  // src/components/pr/TimelineItemView.tsx
122223
122638
  var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1);
@@ -122482,7 +122897,7 @@ function ConversationsTab({
122482
122897
  }) {
122483
122898
  const theme14 = useTheme();
122484
122899
  const { stdout } = use_stdout_default();
122485
- const listRef = (0, import_react79.useRef)(null);
122900
+ const listRef = (0, import_react81.useRef)(null);
122486
122901
  const allTimeline = buildTimeline(pr, comments, reviews, reviewThreads, issueComments);
122487
122902
  const timeline = showResolved ? allTimeline : allTimeline.filter((item) => !item.isResolved);
122488
122903
  const viewportHeight = Math.max(1, (stdout?.rows ?? 24) - CONVERSATIONS_RESERVED_LINES);
@@ -122534,7 +122949,7 @@ function ConversationsTab({
122534
122949
  },
122535
122950
  { isActive: isActive2 }
122536
122951
  );
122537
- (0, import_react79.useEffect)(() => {
122952
+ (0, import_react81.useEffect)(() => {
122538
122953
  const handleResize = () => {
122539
122954
  listRef.current?.remeasure();
122540
122955
  };
@@ -122572,7 +122987,7 @@ function ConversationsTab({
122572
122987
  }
122573
122988
 
122574
122989
  // src/components/pr/CommitsTab.tsx
122575
- var import_react80 = __toESM(require_react(), 1);
122990
+ var import_react82 = __toESM(require_react(), 1);
122576
122991
 
122577
122992
  // src/utils/terminal.ts
122578
122993
  import { execFile as execFile2, execFileSync as execFileSync2 } from "child_process";
@@ -122660,7 +123075,7 @@ function CommitsTab({
122660
123075
  const theme14 = useTheme();
122661
123076
  const { setStatusMessage } = useStatusMessage();
122662
123077
  const viewportHeight = Math.max(1, (stdout?.rows ?? 24) - 10);
122663
- const listRef = (0, import_react80.useRef)(null);
123078
+ const listRef = (0, import_react82.useRef)(null);
122664
123079
  const { selectedIndex } = useListNavigation({
122665
123080
  itemCount: commits.length,
122666
123081
  viewportHeight,
@@ -122679,7 +123094,7 @@ function CommitsTab({
122679
123094
  },
122680
123095
  { isActive: isActive2 }
122681
123096
  );
122682
- (0, import_react80.useEffect)(() => {
123097
+ (0, import_react82.useEffect)(() => {
122683
123098
  const handleResize = () => listRef.current?.remeasure();
122684
123099
  stdout?.on("resize", handleResize);
122685
123100
  return () => {
@@ -122729,10 +123144,10 @@ function CommitsTab({
122729
123144
  }
122730
123145
 
122731
123146
  // src/components/pr/ReviewModal.tsx
122732
- var import_react82 = __toESM(require_react(), 1);
123147
+ var import_react84 = __toESM(require_react(), 1);
122733
123148
 
122734
123149
  // src/components/common/MultiLineInput.tsx
122735
- var import_react81 = __toESM(require_react(), 1);
123150
+ var import_react83 = __toESM(require_react(), 1);
122736
123151
  var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
122737
123152
  function MultiLineInput({
122738
123153
  placeholder,
@@ -122742,12 +123157,12 @@ function MultiLineInput({
122742
123157
  minHeight = 3
122743
123158
  }) {
122744
123159
  const theme14 = useTheme();
122745
- const [lines, setLines] = (0, import_react81.useState)(
123160
+ const [lines, setLines] = (0, import_react83.useState)(
122746
123161
  defaultValue ? defaultValue.split("\n") : [""]
122747
123162
  );
122748
- const [cursorRow, setCursorRow] = (0, import_react81.useState)(0);
122749
- const [cursorCol, setCursorCol] = (0, import_react81.useState)(0);
122750
- const updateLines = (0, import_react81.useCallback)(
123163
+ const [cursorRow, setCursorRow] = (0, import_react83.useState)(0);
123164
+ const [cursorCol, setCursorCol] = (0, import_react83.useState)(0);
123165
+ const updateLines = (0, import_react83.useCallback)(
122751
123166
  (newLines) => {
122752
123167
  setLines(newLines);
122753
123168
  onChange(newLines.join("\n"));
@@ -122883,17 +123298,17 @@ function ReviewModal({
122883
123298
  }) {
122884
123299
  const theme14 = useTheme();
122885
123300
  const { setInputActive } = useInputFocus();
122886
- const [step4, setStep] = (0, import_react82.useState)("select_type");
122887
- const [selectedType, setSelectedType] = (0, import_react82.useState)(0);
122888
- const [reviewEvent, setReviewEvent] = (0, import_react82.useState)("APPROVE");
122889
- const [body, setBody] = (0, import_react82.useState)("");
122890
- (0, import_react82.useEffect)(() => {
123301
+ const [step4, setStep] = (0, import_react84.useState)("select_type");
123302
+ const [selectedType, setSelectedType] = (0, import_react84.useState)(0);
123303
+ const [reviewEvent, setReviewEvent] = (0, import_react84.useState)("APPROVE");
123304
+ const [body, setBody] = (0, import_react84.useState)("");
123305
+ (0, import_react84.useEffect)(() => {
122891
123306
  if (step4 === "enter_body") {
122892
123307
  setInputActive(true);
122893
123308
  }
122894
123309
  return () => setInputActive(false);
122895
123310
  }, [step4, setInputActive]);
122896
- const handleSubmit = (0, import_react82.useCallback)(() => {
123311
+ const handleSubmit = (0, import_react84.useCallback)(() => {
122897
123312
  if (reviewEvent === "REQUEST_CHANGES" && !body.trim()) {
122898
123313
  return;
122899
123314
  }
@@ -123006,7 +123421,7 @@ function ReviewModal({
123006
123421
  }
123007
123422
 
123008
123423
  // src/components/pr/CommentModal.tsx
123009
- var import_react83 = __toESM(require_react(), 1);
123424
+ var import_react85 = __toESM(require_react(), 1);
123010
123425
  var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
123011
123426
  function CommentModal({
123012
123427
  title,
@@ -123019,12 +123434,12 @@ function CommentModal({
123019
123434
  }) {
123020
123435
  const theme14 = useTheme();
123021
123436
  const { setInputActive } = useInputFocus();
123022
- const [body, setBody] = (0, import_react83.useState)(defaultValue ?? "");
123023
- (0, import_react83.useEffect)(() => {
123437
+ const [body, setBody] = (0, import_react85.useState)(defaultValue ?? "");
123438
+ (0, import_react85.useEffect)(() => {
123024
123439
  setInputActive(true);
123025
123440
  return () => setInputActive(false);
123026
123441
  }, [setInputActive]);
123027
- const handleSubmit = (0, import_react83.useCallback)(() => {
123442
+ const handleSubmit = (0, import_react85.useCallback)(() => {
123028
123443
  const trimmed2 = body.trim();
123029
123444
  if (trimmed2 && !isSubmitting) {
123030
123445
  onSubmit(trimmed2);
@@ -123095,7 +123510,7 @@ function CommentModal({
123095
123510
  }
123096
123511
 
123097
123512
  // src/components/pr/MergeModal.tsx
123098
- var import_react84 = __toESM(require_react(), 1);
123513
+ var import_react86 = __toESM(require_react(), 1);
123099
123514
  var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
123100
123515
  var MERGE_METHODS = [
123101
123516
  { method: "merge", label: "Merge Commit", description: "All commits preserved" },
@@ -123129,12 +123544,12 @@ function MergeModal({
123129
123544
  }) {
123130
123545
  const theme14 = useTheme();
123131
123546
  const { setInputActive } = useInputFocus();
123132
- const [step4, setStep] = (0, import_react84.useState)("select_method");
123133
- const [selectedMethod, setSelectedMethod] = (0, import_react84.useState)(0);
123134
- const [commitTitle, setCommitTitle] = (0, import_react84.useState)(`${pr.title} (#${pr.number})`);
123547
+ const [step4, setStep] = (0, import_react86.useState)("select_method");
123548
+ const [selectedMethod, setSelectedMethod] = (0, import_react86.useState)(0);
123549
+ const [commitTitle, setCommitTitle] = (0, import_react86.useState)(`${pr.title} (#${pr.number})`);
123135
123550
  const mergeBlockReason = getMergeabilityMessage(pr);
123136
123551
  const canMerge = mergeBlockReason === null;
123137
- (0, import_react84.useEffect)(() => {
123552
+ (0, import_react86.useEffect)(() => {
123138
123553
  if (step4 === "edit_title") {
123139
123554
  setInputActive(true);
123140
123555
  }
@@ -123291,7 +123706,7 @@ function MergeModal({
123291
123706
  }
123292
123707
 
123293
123708
  // src/components/pr/ReReviewModal.tsx
123294
- var import_react85 = __toESM(require_react(), 1);
123709
+ var import_react87 = __toESM(require_react(), 1);
123295
123710
  var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
123296
123711
  function getStatusColor(status, theme14) {
123297
123712
  switch (status) {
@@ -123349,8 +123764,8 @@ function ReReviewModal({
123349
123764
  error
123350
123765
  }) {
123351
123766
  const theme14 = useTheme();
123352
- const [selectedIndex, setSelectedIndex] = (0, import_react85.useState)(0);
123353
- const [selected, setSelected] = (0, import_react85.useState)(/* @__PURE__ */ new Set());
123767
+ const [selectedIndex, setSelectedIndex] = (0, import_react87.useState)(0);
123768
+ const [selected, setSelected] = (0, import_react87.useState)(/* @__PURE__ */ new Set());
123354
123769
  use_input_default(
123355
123770
  (_input, key) => {
123356
123771
  if (isSubmitting) return;
@@ -123563,8 +123978,8 @@ function parseGitHubUrl(url2) {
123563
123978
  }
123564
123979
 
123565
123980
  // src/hooks/useReadState.ts
123566
- var import_react86 = __toESM(require_react(), 1);
123567
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
123981
+ var import_react88 = __toESM(require_react(), 1);
123982
+ import { readFileSync as readFileSync3 } from "fs";
123568
123983
  import { join as join6 } from "path";
123569
123984
  import { homedir as homedir4 } from "os";
123570
123985
  var CONFIG_DIR3 = join6(homedir4(), ".config", "lazyreview");
@@ -123579,13 +123994,6 @@ function loadFromDisk2() {
123579
123994
  return {};
123580
123995
  }
123581
123996
  }
123582
- function saveToDisk2(data) {
123583
- try {
123584
- mkdirSync2(CONFIG_DIR3, { recursive: true });
123585
- writeFileSync2(READ_STATE_FILE, JSON.stringify(data, null, 2), "utf-8");
123586
- } catch {
123587
- }
123588
- }
123589
123997
  function pruneOldEntries2(data) {
123590
123998
  const now2 = Date.now();
123591
123999
  const result = {};
@@ -123598,9 +124006,10 @@ function pruneOldEntries2(data) {
123598
124006
  return result;
123599
124007
  }
123600
124008
  function createReadStateStore() {
124009
+ const writer = createDebouncedWriter(READ_STATE_FILE);
123601
124010
  let data = pruneOldEntries2(loadFromDisk2());
123602
124011
  let listeners2 = [];
123603
- saveToDisk2(data);
124012
+ writer.schedule(data);
123604
124013
  const notify2 = () => {
123605
124014
  listeners2.forEach((l) => l());
123606
124015
  };
@@ -123620,7 +124029,7 @@ function createReadStateStore() {
123620
124029
  ...data,
123621
124030
  [htmlUrl]: { lastSeenAt: now2, prUpdatedAt }
123622
124031
  };
123623
- saveToDisk2(data);
124032
+ writer.schedule(data);
123624
124033
  notify2();
123625
124034
  },
123626
124035
  isUnread(htmlUrl, prUpdatedAt) {
@@ -123632,18 +124041,18 @@ function createReadStateStore() {
123632
124041
  }
123633
124042
  var store5 = createReadStateStore();
123634
124043
  function useReadState() {
123635
- const readState = (0, import_react86.useSyncExternalStore)(
124044
+ const readState = (0, import_react88.useSyncExternalStore)(
123636
124045
  store5.subscribe,
123637
124046
  store5.getSnapshot,
123638
124047
  () => ({})
123639
124048
  );
123640
- const markAsRead = (0, import_react86.useCallback)(
124049
+ const markAsRead = (0, import_react88.useCallback)(
123641
124050
  (htmlUrl, prUpdatedAt) => {
123642
124051
  store5.markAsRead(htmlUrl, prUpdatedAt);
123643
124052
  },
123644
124053
  []
123645
124054
  );
123646
- const isUnread = (0, import_react86.useCallback)(
124055
+ const isUnread = (0, import_react88.useCallback)(
123647
124056
  (htmlUrl, prUpdatedAt) => {
123648
124057
  return store5.isUnread(htmlUrl, prUpdatedAt);
123649
124058
  },
@@ -123655,14 +124064,14 @@ function useReadState() {
123655
124064
  }
123656
124065
 
123657
124066
  // src/hooks/useManualRefresh.ts
123658
- var import_react87 = __toESM(require_react(), 1);
124067
+ var import_react89 = __toESM(require_react(), 1);
123659
124068
  function useManualRefresh({
123660
124069
  isActive: isActive2 = true,
123661
124070
  queryKeys
123662
124071
  } = {}) {
123663
124072
  const queryClient2 = useQueryClient();
123664
124073
  const { setStatusMessage } = useStatusMessage();
123665
- const refresh = (0, import_react87.useCallback)(() => {
124074
+ const refresh = (0, import_react89.useCallback)(() => {
123666
124075
  if (queryKeys && queryKeys.length > 0) {
123667
124076
  queryKeys.forEach((key) => {
123668
124077
  queryClient2.invalidateQueries({ queryKey: key });
@@ -123699,17 +124108,17 @@ function PRDetailScreen({
123699
124108
  const { setStatusMessage } = useStatusMessage();
123700
124109
  const { markAsRead } = useReadState();
123701
124110
  const theme14 = useTheme();
123702
- const [currentTab, setCurrentTab] = (0, import_react88.useState)(0);
123703
- const [showDiscardConfirm, setShowDiscardConfirm] = (0, import_react88.useState)(false);
124111
+ const [currentTab, setCurrentTab] = (0, import_react90.useState)(0);
124112
+ const [showDiscardConfirm, setShowDiscardConfirm] = (0, import_react90.useState)(false);
123704
124113
  const contentHeight = Math.max(1, (stdout?.rows ?? 24) - PR_DETAIL_RESERVED_LINES);
123705
- import_react88.default.useEffect(() => {
124114
+ import_react90.default.useEffect(() => {
123706
124115
  markAsRead(pr.html_url, pr.updated_at);
123707
124116
  }, [pr.html_url, pr.updated_at, markAsRead]);
123708
- import_react88.default.useEffect(() => {
124117
+ import_react90.default.useEffect(() => {
123709
124118
  const tabContexts = [
123710
124119
  "pr-detail-conversations",
123711
- "pr-detail-files",
123712
- "pr-detail-commits"
124120
+ "pr-detail-commits",
124121
+ "pr-detail-files"
123713
124122
  ];
123714
124123
  setScreenContext(tabContexts[currentTab] ?? "pr-detail-conversations");
123715
124124
  }, [currentTab]);
@@ -123738,7 +124147,7 @@ function PRDetailScreen({
123738
124147
  prNumber: pr.number,
123739
124148
  setStatusMessage
123740
124149
  });
123741
- const handleReviewSubmit = (0, import_react88.useCallback)(
124150
+ const handleReviewSubmit = (0, import_react90.useCallback)(
123742
124151
  (body, event) => {
123743
124152
  if (pendingReview.isActive) {
123744
124153
  pendingReview.submitReview(body, event);
@@ -123749,7 +124158,7 @@ function PRDetailScreen({
123749
124158
  },
123750
124159
  [pendingReview, modals]
123751
124160
  );
123752
- const handleCommentSubmit = (0, import_react88.useCallback)(
124161
+ const handleCommentSubmit = (0, import_react90.useCallback)(
123753
124162
  (body) => {
123754
124163
  if (pendingReview.isActive && modals.inlineContext) {
123755
124164
  pendingReview.addPendingComment(
@@ -123811,8 +124220,6 @@ function PRDetailScreen({
123811
124220
  if (!pendingReview.isActive) {
123812
124221
  pendingReview.startReview();
123813
124222
  }
123814
- } else if (input === "r" && currentTab !== 0) {
123815
- modals.openReviewModal();
123816
124223
  } else if (input === "R") {
123817
124224
  modals.openReviewModal();
123818
124225
  } else if (input === "E") {
@@ -123834,9 +124241,14 @@ function PRDetailScreen({
123834
124241
  setStatusMessage("Checking out PR #" + pr.number + "...", 1e4);
123835
124242
  checkoutPR(pr.number).then((result) => {
123836
124243
  setStatusMessage(
123837
- result.success ? result.message : result.message,
124244
+ result.message,
123838
124245
  result.success ? 3e3 : 5e3
123839
124246
  );
124247
+ }).catch((error) => {
124248
+ setStatusMessage(
124249
+ `Checkout failed: ${error instanceof Error ? error.message : String(error)}`,
124250
+ 5e3
124251
+ );
123840
124252
  });
123841
124253
  } else if (input === "q" || key.escape) {
123842
124254
  if (pendingReview.isActive) {
@@ -123980,22 +124392,22 @@ function PRDetailScreen({
123980
124392
  }
123981
124393
 
123982
124394
  // src/screens/MyPRsScreen.tsx
123983
- var import_react96 = __toESM(require_react(), 1);
124395
+ var import_react98 = __toESM(require_react(), 1);
123984
124396
 
123985
124397
  // src/screens/PRListScreen.tsx
123986
- var import_react95 = __toESM(require_react(), 1);
124398
+ var import_react97 = __toESM(require_react(), 1);
123987
124399
 
123988
124400
  // src/hooks/usePagination.ts
123989
- var import_react89 = __toESM(require_react(), 1);
124401
+ var import_react91 = __toESM(require_react(), 1);
123990
124402
  function usePagination(items, options = {}) {
123991
124403
  const pageSize = options.pageSize ?? 18;
123992
- const [currentPage, setCurrentPage] = (0, import_react89.useState)(1);
123993
- const prevItemsLengthRef = (0, import_react89.useRef)(items.length);
123994
- const totalPages = (0, import_react89.useMemo)(
124404
+ const [currentPage, setCurrentPage] = (0, import_react91.useState)(1);
124405
+ const prevItemsLengthRef = (0, import_react91.useRef)(items.length);
124406
+ const totalPages = (0, import_react91.useMemo)(
123995
124407
  () => Math.max(1, Math.ceil(items.length / pageSize)),
123996
124408
  [items.length, pageSize]
123997
124409
  );
123998
- (0, import_react89.useEffect)(() => {
124410
+ (0, import_react91.useEffect)(() => {
123999
124411
  if (items.length !== prevItemsLengthRef.current) {
124000
124412
  setCurrentPage(1);
124001
124413
  prevItemsLengthRef.current = items.length;
@@ -124004,23 +124416,23 @@ function usePagination(items, options = {}) {
124004
124416
  const safePage = Math.min(currentPage, totalPages);
124005
124417
  const startIndex = (safePage - 1) * pageSize;
124006
124418
  const endIndex = Math.min(startIndex + pageSize, items.length);
124007
- const pageItems = (0, import_react89.useMemo)(
124419
+ const pageItems = (0, import_react91.useMemo)(
124008
124420
  () => items.slice(startIndex, endIndex),
124009
124421
  [items, startIndex, endIndex]
124010
124422
  );
124011
124423
  const hasNextPage = safePage < totalPages;
124012
124424
  const hasPrevPage = safePage > 1;
124013
- const nextPage = (0, import_react89.useCallback)(() => {
124425
+ const nextPage = (0, import_react91.useCallback)(() => {
124014
124426
  if (hasNextPage) {
124015
124427
  setCurrentPage((p) => p + 1);
124016
124428
  }
124017
124429
  }, [hasNextPage]);
124018
- const prevPage = (0, import_react89.useCallback)(() => {
124430
+ const prevPage = (0, import_react91.useCallback)(() => {
124019
124431
  if (hasPrevPage) {
124020
124432
  setCurrentPage((p) => p - 1);
124021
124433
  }
124022
124434
  }, [hasPrevPage]);
124023
- const goToPage = (0, import_react89.useCallback)(
124435
+ const goToPage = (0, import_react91.useCallback)(
124024
124436
  (page) => {
124025
124437
  const clampedPage = Math.max(1, Math.min(page, totalPages));
124026
124438
  setCurrentPage(clampedPage);
@@ -124042,7 +124454,7 @@ function usePagination(items, options = {}) {
124042
124454
  }
124043
124455
 
124044
124456
  // src/hooks/useFilter.ts
124045
- var import_react90 = __toESM(require_react(), 1);
124457
+ var import_react92 = __toESM(require_react(), 1);
124046
124458
  var defaultFilter = {
124047
124459
  search: "",
124048
124460
  repo: null,
@@ -124099,8 +124511,8 @@ function comparePRs(a, b, sortBy, sortDirection) {
124099
124511
  return sortDirection === "asc" ? -comparison : comparison;
124100
124512
  }
124101
124513
  function useFilter(items) {
124102
- const [filter9, setFilter] = (0, import_react90.useState)(defaultFilter);
124103
- const availableRepos = (0, import_react90.useMemo)(() => {
124514
+ const [filter9, setFilter] = (0, import_react92.useState)(defaultFilter);
124515
+ const availableRepos = (0, import_react92.useMemo)(() => {
124104
124516
  const repos = /* @__PURE__ */ new Set();
124105
124517
  items.forEach((pr) => {
124106
124518
  const repo = extractRepoFromUrl(pr.html_url);
@@ -124108,17 +124520,17 @@ function useFilter(items) {
124108
124520
  });
124109
124521
  return Array.from(repos).sort();
124110
124522
  }, [items]);
124111
- const availableAuthors = (0, import_react90.useMemo)(() => {
124523
+ const availableAuthors = (0, import_react92.useMemo)(() => {
124112
124524
  const authors = /* @__PURE__ */ new Set();
124113
124525
  items.forEach((pr) => authors.add(pr.user.login));
124114
124526
  return Array.from(authors).sort();
124115
124527
  }, [items]);
124116
- const availableLabels = (0, import_react90.useMemo)(() => {
124528
+ const availableLabels = (0, import_react92.useMemo)(() => {
124117
124529
  const labels = /* @__PURE__ */ new Set();
124118
124530
  items.forEach((pr) => pr.labels.forEach((l) => labels.add(l.name)));
124119
124531
  return Array.from(labels).sort();
124120
124532
  }, [items]);
124121
- const repoFacets = (0, import_react90.useMemo)(() => {
124533
+ const repoFacets = (0, import_react92.useMemo)(() => {
124122
124534
  const counts = /* @__PURE__ */ new Map();
124123
124535
  items.forEach((pr) => {
124124
124536
  const repo = extractRepoFromUrl(pr.html_url);
@@ -124126,14 +124538,14 @@ function useFilter(items) {
124126
124538
  });
124127
124539
  return Array.from(counts.entries()).map(([value5, count]) => ({ value: value5, count })).sort((a, b) => b.count - a.count);
124128
124540
  }, [items]);
124129
- const authorFacets = (0, import_react90.useMemo)(() => {
124541
+ const authorFacets = (0, import_react92.useMemo)(() => {
124130
124542
  const counts = /* @__PURE__ */ new Map();
124131
124543
  items.forEach((pr) => {
124132
124544
  counts.set(pr.user.login, (counts.get(pr.user.login) ?? 0) + 1);
124133
124545
  });
124134
124546
  return Array.from(counts.entries()).map(([value5, count]) => ({ value: value5, count })).sort((a, b) => b.count - a.count);
124135
124547
  }, [items]);
124136
- const labelFacets = (0, import_react90.useMemo)(() => {
124548
+ const labelFacets = (0, import_react92.useMemo)(() => {
124137
124549
  const counts = /* @__PURE__ */ new Map();
124138
124550
  items.forEach(
124139
124551
  (pr) => pr.labels.forEach((l) => {
@@ -124142,31 +124554,31 @@ function useFilter(items) {
124142
124554
  );
124143
124555
  return Array.from(counts.entries()).map(([value5, count]) => ({ value: value5, count })).sort((a, b) => b.count - a.count);
124144
124556
  }, [items]);
124145
- const filteredItems = (0, import_react90.useMemo)(() => {
124557
+ const filteredItems = (0, import_react92.useMemo)(() => {
124146
124558
  return items.filter((pr) => matchesSearch(pr, filter9.search)).filter((pr) => matchesRepo(pr, filter9.repo)).filter((pr) => matchesAuthor(pr, filter9.author)).filter((pr) => matchesLabel(pr, filter9.label)).sort((a, b) => comparePRs(a, b, filter9.sortBy, filter9.sortDirection));
124147
124559
  }, [items, filter9]);
124148
- const setSearch = (0, import_react90.useCallback)((search) => {
124560
+ const setSearch = (0, import_react92.useCallback)((search) => {
124149
124561
  setFilter((prev) => ({ ...prev, search }));
124150
124562
  }, []);
124151
- const setRepo = (0, import_react90.useCallback)((repo) => {
124563
+ const setRepo = (0, import_react92.useCallback)((repo) => {
124152
124564
  setFilter((prev) => ({ ...prev, repo }));
124153
124565
  }, []);
124154
- const setAuthor = (0, import_react90.useCallback)((author) => {
124566
+ const setAuthor = (0, import_react92.useCallback)((author) => {
124155
124567
  setFilter((prev) => ({ ...prev, author }));
124156
124568
  }, []);
124157
- const setLabel = (0, import_react90.useCallback)((label) => {
124569
+ const setLabel = (0, import_react92.useCallback)((label) => {
124158
124570
  setFilter((prev) => ({ ...prev, label }));
124159
124571
  }, []);
124160
- const setSortBy = (0, import_react90.useCallback)((sortBy) => {
124572
+ const setSortBy = (0, import_react92.useCallback)((sortBy) => {
124161
124573
  setFilter((prev) => ({ ...prev, sortBy }));
124162
124574
  }, []);
124163
- const toggleSortDirection = (0, import_react90.useCallback)(() => {
124575
+ const toggleSortDirection = (0, import_react92.useCallback)(() => {
124164
124576
  setFilter((prev) => ({
124165
124577
  ...prev,
124166
124578
  sortDirection: prev.sortDirection === "asc" ? "desc" : "asc"
124167
124579
  }));
124168
124580
  }, []);
124169
- const clearFilters = (0, import_react90.useCallback)(() => {
124581
+ const clearFilters = (0, import_react92.useCallback)(() => {
124170
124582
  setFilter(defaultFilter);
124171
124583
  }, []);
124172
124584
  const hasActiveFilters = filter9.search !== "" || filter9.repo !== null || filter9.author !== null || filter9.label !== null;
@@ -124412,7 +124824,7 @@ function PaginationBar({
124412
124824
  }
124413
124825
 
124414
124826
  // src/components/common/FilterModal.tsx
124415
- var import_react91 = __toESM(require_react(), 1);
124827
+ var import_react93 = __toESM(require_react(), 1);
124416
124828
  var import_jsx_runtime41 = __toESM(require_jsx_runtime(), 1);
124417
124829
  var FILTER_FIELDS = ["search", "repo", "author", "label"];
124418
124830
  function FacetSection({
@@ -124485,17 +124897,17 @@ function FilterModal({
124485
124897
  }) {
124486
124898
  const theme14 = useTheme();
124487
124899
  const { setInputActive } = useInputFocus();
124488
- const [activeField, setActiveField] = (0, import_react91.useState)("search");
124489
- const [searchValue, setSearchValue] = (0, import_react91.useState)(filter9.search);
124490
- const [repoIndex, setRepoIndex] = (0, import_react91.useState)(0);
124491
- const [authorIndex, setAuthorIndex] = (0, import_react91.useState)(0);
124492
- const [labelIndex, setLabelIndex] = (0, import_react91.useState)(0);
124900
+ const [activeField, setActiveField] = (0, import_react93.useState)("search");
124901
+ const [searchValue, setSearchValue] = (0, import_react93.useState)(filter9.search);
124902
+ const [repoIndex, setRepoIndex] = (0, import_react93.useState)(0);
124903
+ const [authorIndex, setAuthorIndex] = (0, import_react93.useState)(0);
124904
+ const [labelIndex, setLabelIndex] = (0, import_react93.useState)(0);
124493
124905
  const isSearchField = activeField === "search";
124494
- (0, import_react91.useEffect)(() => {
124906
+ (0, import_react93.useEffect)(() => {
124495
124907
  setInputActive(isSearchField);
124496
124908
  return () => setInputActive(false);
124497
124909
  }, [setInputActive, isSearchField]);
124498
- (0, import_react91.useEffect)(() => {
124910
+ (0, import_react93.useEffect)(() => {
124499
124911
  onSearchChange(searchValue);
124500
124912
  }, [searchValue, onSearchChange]);
124501
124913
  const getMaxIndex = (field) => {
@@ -124658,24 +125070,24 @@ function FilterModal({
124658
125070
  }
124659
125071
 
124660
125072
  // src/components/common/SortModal.tsx
124661
- var import_react94 = __toESM(require_react(), 1);
125073
+ var import_react96 = __toESM(require_react(), 1);
124662
125074
 
124663
125075
  // node_modules/.pnpm/ink-select-input@6.2.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-select-input/build/Indicator.js
124664
- var import_react92 = __toESM(require_react(), 1);
125076
+ var import_react94 = __toESM(require_react(), 1);
124665
125077
  function Indicator({ isSelected = false }) {
124666
- return import_react92.default.createElement(Box_default, { marginRight: 1 }, isSelected ? import_react92.default.createElement(Text, { color: "blue" }, figures_default.pointer) : import_react92.default.createElement(Text, null, " "));
125078
+ return import_react94.default.createElement(Box_default, { marginRight: 1 }, isSelected ? import_react94.default.createElement(Text, { color: "blue" }, figures_default.pointer) : import_react94.default.createElement(Text, null, " "));
124667
125079
  }
124668
125080
  var Indicator_default = Indicator;
124669
125081
 
124670
125082
  // node_modules/.pnpm/ink-select-input@6.2.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-select-input/build/Item.js
124671
- var React52 = __toESM(require_react(), 1);
125083
+ var React53 = __toESM(require_react(), 1);
124672
125084
  function Item({ isSelected = false, label }) {
124673
- return React52.createElement(Text, { color: isSelected ? "blue" : void 0 }, label);
125085
+ return React53.createElement(Text, { color: isSelected ? "blue" : void 0 }, label);
124674
125086
  }
124675
125087
  var Item_default = Item;
124676
125088
 
124677
125089
  // node_modules/.pnpm/ink-select-input@6.2.0_ink@6.7.0_@types+react@19.2.13_react@19.2.4__react@19.2.4/node_modules/ink-select-input/build/SelectInput.js
124678
- var import_react93 = __toESM(require_react(), 1);
125090
+ var import_react95 = __toESM(require_react(), 1);
124679
125091
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
124680
125092
 
124681
125093
  // node_modules/.pnpm/to-rotated@1.0.0/node_modules/to-rotated/index.js
@@ -124705,17 +125117,17 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
124705
125117
  const hasLimit = typeof customLimit === "number" && items.length > customLimit;
124706
125118
  const limit = hasLimit ? Math.min(customLimit, items.length) : items.length;
124707
125119
  const lastIndex = limit - 1;
124708
- const [rotateIndex, setRotateIndex] = (0, import_react93.useState)(initialIndex > lastIndex ? lastIndex - initialIndex : 0);
124709
- const [selectedIndex, setSelectedIndex] = (0, import_react93.useState)(initialIndex ? initialIndex > lastIndex ? lastIndex : initialIndex : 0);
124710
- const previousItems = (0, import_react93.useRef)(items);
124711
- (0, import_react93.useEffect)(() => {
125120
+ const [rotateIndex, setRotateIndex] = (0, import_react95.useState)(initialIndex > lastIndex ? lastIndex - initialIndex : 0);
125121
+ const [selectedIndex, setSelectedIndex] = (0, import_react95.useState)(initialIndex ? initialIndex > lastIndex ? lastIndex : initialIndex : 0);
125122
+ const previousItems = (0, import_react95.useRef)(items);
125123
+ (0, import_react95.useEffect)(() => {
124712
125124
  if (!isDeepStrictEqual3(previousItems.current.map((item) => item.value), items.map((item) => item.value))) {
124713
125125
  setRotateIndex(0);
124714
125126
  setSelectedIndex(0);
124715
125127
  }
124716
125128
  previousItems.current = items;
124717
125129
  }, [items]);
124718
- use_input_default((0, import_react93.useCallback)((input, key) => {
125130
+ use_input_default((0, import_react95.useCallback)((input, key) => {
124719
125131
  if (input === "k" || key.upArrow) {
124720
125132
  const lastIndex2 = (hasLimit ? limit : items.length) - 1;
124721
125133
  const atFirstIndex = selectedIndex === 0;
@@ -124767,15 +125179,15 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
124767
125179
  onHighlight
124768
125180
  ]), { isActive: isFocused });
124769
125181
  const slicedItems = hasLimit ? toRotated(items, rotateIndex).slice(0, limit) : items;
124770
- return import_react93.default.createElement(Box_default, { flexDirection: "column" }, slicedItems.map((item, index) => {
125182
+ return import_react95.default.createElement(Box_default, { flexDirection: "column" }, slicedItems.map((item, index) => {
124771
125183
  const isSelected = index === selectedIndex;
124772
125184
  return (
124773
125185
  // @ts-expect-error - `key` can't be optional but `item.value` is generic T
124774
- import_react93.default.createElement(
125186
+ import_react95.default.createElement(
124775
125187
  Box_default,
124776
125188
  { key: item.key ?? item.value },
124777
- import_react93.default.createElement(indicatorComponent, { isSelected }),
124778
- import_react93.default.createElement(itemComponent, { ...item, isSelected })
125189
+ import_react95.default.createElement(indicatorComponent, { isSelected }),
125190
+ import_react95.default.createElement(itemComponent, { ...item, isSelected })
124779
125191
  )
124780
125192
  );
124781
125193
  }));
@@ -124804,7 +125216,7 @@ function SortModal({
124804
125216
  onClose();
124805
125217
  }
124806
125218
  });
124807
- const items = (0, import_react94.useMemo)(
125219
+ const items = (0, import_react96.useMemo)(
124808
125220
  () => SORT_OPTIONS.map((option7) => ({
124809
125221
  label: `${option7.label}${option7.key === currentSort ? sortDirection === "desc" ? " \u2193" : " \u2191" : ""}`,
124810
125222
  value: option7.key
@@ -124873,9 +125285,9 @@ function PRListScreen({
124873
125285
  const theme14 = useTheme();
124874
125286
  const { setStatusMessage } = useStatusMessage();
124875
125287
  const { isUnread } = useReadState();
124876
- const [showFilter, setShowFilter] = (0, import_react95.useState)(false);
124877
- const [showSort, setShowSort] = (0, import_react95.useState)(false);
124878
- const [showUnreadOnly, setShowUnreadOnly] = (0, import_react95.useState)(false);
125288
+ const [showFilter, setShowFilter] = (0, import_react97.useState)(false);
125289
+ const [showSort, setShowSort] = (0, import_react97.useState)(false);
125290
+ const [showUnreadOnly, setShowUnreadOnly] = (0, import_react97.useState)(false);
124879
125291
  const { refresh } = useManualRefresh({
124880
125292
  isActive: !showFilter && !showSort,
124881
125293
  queryKeys
@@ -124898,7 +125310,7 @@ function PRListScreen({
124898
125310
  authorFacets,
124899
125311
  labelFacets
124900
125312
  } = useFilter(prs);
124901
- const displayItems = (0, import_react95.useMemo)(
125313
+ const displayItems = (0, import_react97.useMemo)(
124902
125314
  () => showUnreadOnly ? filteredItems.filter((pr) => isUnread(pr.html_url, pr.updated_at)) : filteredItems,
124903
125315
  [filteredItems, showUnreadOnly, isUnread]
124904
125316
  );
@@ -125034,7 +125446,7 @@ function PRListScreen({
125034
125446
  // src/screens/MyPRsScreen.tsx
125035
125447
  var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
125036
125448
  function MyPRsScreen({ onSelect }) {
125037
- const [stateFilter, setStateFilter] = (0, import_react96.useState)("open");
125449
+ const [stateFilter, setStateFilter] = (0, import_react98.useState)("open");
125038
125450
  const { data: prs = [], isLoading, error } = useMyPRs(stateFilter);
125039
125451
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
125040
125452
  PRListScreen,
@@ -125054,10 +125466,10 @@ function MyPRsScreen({ onSelect }) {
125054
125466
  }
125055
125467
 
125056
125468
  // src/screens/ReviewRequestsScreen.tsx
125057
- var import_react97 = __toESM(require_react(), 1);
125469
+ var import_react99 = __toESM(require_react(), 1);
125058
125470
  var import_jsx_runtime45 = __toESM(require_jsx_runtime(), 1);
125059
125471
  function ReviewRequestsScreen({ onSelect }) {
125060
- const [stateFilter, setStateFilter] = (0, import_react97.useState)("open");
125472
+ const [stateFilter, setStateFilter] = (0, import_react99.useState)("open");
125061
125473
  const { data: prs = [], isLoading, error } = useReviewRequests(stateFilter);
125062
125474
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
125063
125475
  PRListScreen,
@@ -125077,7 +125489,7 @@ function ReviewRequestsScreen({ onSelect }) {
125077
125489
  }
125078
125490
 
125079
125491
  // src/screens/SettingsScreen.tsx
125080
- var import_react98 = __toESM(require_react(), 1);
125492
+ var import_react100 = __toESM(require_react(), 1);
125081
125493
 
125082
125494
  // src/hooks/useAuth.ts
125083
125495
  function useAuth() {
@@ -125255,10 +125667,10 @@ function SettingsScreen() {
125255
125667
  } = useAuth();
125256
125668
  const { setStatusMessage } = useStatusMessage();
125257
125669
  const { setInputActive } = useInputFocus();
125258
- const [selectedItem, setSelectedItem] = (0, import_react98.useState)("token_source");
125259
- const [editingField, setEditingField] = (0, import_react98.useState)(null);
125260
- const [editValue, setEditValue] = (0, import_react98.useState)("");
125261
- const [tokenMessage, setTokenMessage] = (0, import_react98.useState)(null);
125670
+ const [selectedItem, setSelectedItem] = (0, import_react100.useState)("token_source");
125671
+ const [editingField, setEditingField] = (0, import_react100.useState)(null);
125672
+ const [editValue, setEditValue] = (0, import_react100.useState)("");
125673
+ const [tokenMessage, setTokenMessage] = (0, import_react100.useState)(null);
125262
125674
  const isEditing = editingField !== null;
125263
125675
  const cycleTheme = () => {
125264
125676
  const currentTheme = config2?.theme ?? "tokyo-night";
@@ -125475,7 +125887,8 @@ function SettingsScreen() {
125475
125887
  SettingRow,
125476
125888
  {
125477
125889
  label: "Provider",
125478
- value: config2?.provider ?? "github"
125890
+ value: config2?.provider ?? "github",
125891
+ hint: config2?.provider === "gitlab" ? "(gitlab support coming soon)" : void 0
125479
125892
  }
125480
125893
  ),
125481
125894
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
@@ -125510,10 +125923,10 @@ function SettingsScreen() {
125510
125923
  }
125511
125924
 
125512
125925
  // src/screens/InvolvedScreen.tsx
125513
- var import_react99 = __toESM(require_react(), 1);
125926
+ var import_react101 = __toESM(require_react(), 1);
125514
125927
  var import_jsx_runtime48 = __toESM(require_jsx_runtime(), 1);
125515
125928
  function InvolvedScreen({ onSelect }) {
125516
- const [stateFilter, setStateFilter] = (0, import_react99.useState)("open");
125929
+ const [stateFilter, setStateFilter] = (0, import_react101.useState)("open");
125517
125930
  const { data: prs = [], isLoading, error } = useInvolvedPRs(stateFilter);
125518
125931
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
125519
125932
  PRListScreen,
@@ -125533,10 +125946,10 @@ function InvolvedScreen({ onSelect }) {
125533
125946
  }
125534
125947
 
125535
125948
  // src/screens/ThisRepoScreen.tsx
125536
- var import_react100 = __toESM(require_react(), 1);
125949
+ var import_react102 = __toESM(require_react(), 1);
125537
125950
  var import_jsx_runtime49 = __toESM(require_jsx_runtime(), 1);
125538
125951
  function ThisRepoScreen({ owner, repo, onSelect }) {
125539
- const [stateFilter, setStateFilter] = (0, import_react100.useState)("open");
125952
+ const [stateFilter, setStateFilter] = (0, import_react102.useState)("open");
125540
125953
  const { data: prs = [], isLoading, error } = usePullRequests(
125541
125954
  owner ?? "",
125542
125955
  repo ?? "",
@@ -125563,24 +125976,24 @@ function ThisRepoScreen({ owner, repo, onSelect }) {
125563
125976
  }
125564
125977
 
125565
125978
  // src/hooks/useActivePanel.ts
125566
- var import_react101 = __toESM(require_react(), 1);
125979
+ var import_react103 = __toESM(require_react(), 1);
125567
125980
  function useActivePanel({
125568
125981
  hasSelection
125569
125982
  }) {
125570
- const [activePanel, setActivePanel] = (0, import_react101.useState)("sidebar");
125571
- (0, import_react101.useEffect)(() => {
125983
+ const [activePanel, setActivePanel] = (0, import_react103.useState)("sidebar");
125984
+ (0, import_react103.useEffect)(() => {
125572
125985
  if (!hasSelection && activePanel === "detail") {
125573
125986
  setActivePanel("list");
125574
125987
  }
125575
125988
  }, [hasSelection, activePanel]);
125576
- const handleEscape = (0, import_react101.useCallback)(() => {
125989
+ const handleEscape = (0, import_react103.useCallback)(() => {
125577
125990
  if (activePanel === "detail") {
125578
125991
  setActivePanel("list");
125579
125992
  } else if (activePanel === "list") {
125580
125993
  setActivePanel("sidebar");
125581
125994
  }
125582
125995
  }, [activePanel]);
125583
- const handleTab = (0, import_react101.useCallback)(() => {
125996
+ const handleTab = (0, import_react103.useCallback)(() => {
125584
125997
  if (activePanel === "sidebar") {
125585
125998
  setActivePanel("list");
125586
125999
  } else if (activePanel === "list" && hasSelection) {
@@ -125599,6 +126012,91 @@ function useActivePanel({
125599
126012
  return { activePanel, setActivePanel };
125600
126013
  }
125601
126014
 
126015
+ // src/hooks/useSidebarCounts.ts
126016
+ var import_react104 = __toESM(require_react(), 1);
126017
+ var EMPTY_COUNTS = {
126018
+ involved: null,
126019
+ myPrs: null,
126020
+ forReview: null,
126021
+ forReviewUnread: null,
126022
+ thisRepo: null
126023
+ };
126024
+ function extractCount(queryClient2, keyPrefix) {
126025
+ const queries = queryClient2.getQueriesData({
126026
+ queryKey: [keyPrefix],
126027
+ exact: false
126028
+ });
126029
+ for (const [, data] of queries) {
126030
+ if (data !== void 0) {
126031
+ return data.length;
126032
+ }
126033
+ }
126034
+ return null;
126035
+ }
126036
+ function extractThisRepoCount(queryClient2) {
126037
+ const queries = queryClient2.getQueriesData({
126038
+ queryKey: ["prs"],
126039
+ exact: false
126040
+ });
126041
+ for (const [, data] of queries) {
126042
+ if (data !== void 0) {
126043
+ return data.length;
126044
+ }
126045
+ }
126046
+ return null;
126047
+ }
126048
+ function useSidebarCounts(isUnread) {
126049
+ const queryClient2 = useQueryClient();
126050
+ const countsRef = (0, import_react104.useRef)(EMPTY_COUNTS);
126051
+ const computeCounts = (0, import_react104.useCallback)(() => {
126052
+ const involved = extractCount(queryClient2, "involved-prs");
126053
+ const myPrs = extractCount(queryClient2, "my-prs");
126054
+ const forReview = extractCount(queryClient2, "review-requests");
126055
+ const thisRepo = extractThisRepoCount(queryClient2);
126056
+ let forReviewUnread = null;
126057
+ if (forReview !== null) {
126058
+ const reviewQueries = queryClient2.getQueriesData({
126059
+ queryKey: ["review-requests"],
126060
+ exact: false
126061
+ });
126062
+ let unreadCount = 0;
126063
+ for (const [, data] of reviewQueries) {
126064
+ if (data !== void 0) {
126065
+ for (const pr of data) {
126066
+ if (isUnread(pr.html_url, pr.updated_at)) {
126067
+ unreadCount++;
126068
+ }
126069
+ }
126070
+ break;
126071
+ }
126072
+ }
126073
+ forReviewUnread = unreadCount > 0 ? unreadCount : null;
126074
+ }
126075
+ return { involved, myPrs, forReview, forReviewUnread, thisRepo };
126076
+ }, [queryClient2, isUnread]);
126077
+ const subscribe2 = (0, import_react104.useCallback)(
126078
+ (onStoreChange) => {
126079
+ const unsubscribe = queryClient2.getQueryCache().subscribe(() => {
126080
+ const next = computeCounts();
126081
+ const prev = countsRef.current;
126082
+ if (next.involved !== prev.involved || next.myPrs !== prev.myPrs || next.forReview !== prev.forReview || next.forReviewUnread !== prev.forReviewUnread || next.thisRepo !== prev.thisRepo) {
126083
+ countsRef.current = next;
126084
+ onStoreChange();
126085
+ }
126086
+ });
126087
+ return unsubscribe;
126088
+ },
126089
+ [queryClient2, computeCounts]
126090
+ );
126091
+ const getSnapshot2 = (0, import_react104.useCallback)(() => {
126092
+ return countsRef.current;
126093
+ }, []);
126094
+ (0, import_react104.useEffect)(() => {
126095
+ countsRef.current = computeCounts();
126096
+ }, [computeCounts]);
126097
+ return (0, import_react104.useSyncExternalStore)(subscribe2, getSnapshot2, () => EMPTY_COUNTS);
126098
+ }
126099
+
125602
126100
  // src/app.tsx
125603
126101
  var import_jsx_runtime50 = __toESM(require_jsx_runtime(), 1);
125604
126102
  function AppContent({
@@ -125608,30 +126106,35 @@ function AppContent({
125608
126106
  const { exit: exit4 } = use_app_default();
125609
126107
  const { stdout } = use_stdout_default();
125610
126108
  const { user, isAuthenticated, loading, saveToken, error } = useAuth();
125611
- const [sidebarVisible, setSidebarVisible] = (0, import_react102.useState)(true);
125612
- const [currentScreen, setCurrentScreen] = (0, import_react102.useState)({
126109
+ const [sidebarVisible, setSidebarVisible] = (0, import_react105.useState)(true);
126110
+ const [currentScreen, setCurrentScreen] = (0, import_react105.useState)({
125613
126111
  type: "list"
125614
126112
  });
125615
- const [tokenError, setTokenError] = (0, import_react102.useState)(null);
125616
- const [showHelp, setShowHelp] = (0, import_react102.useState)(false);
125617
- const [showTokenInput, setShowTokenInput] = (0, import_react102.useState)(false);
126113
+ const [tokenError, setTokenError] = (0, import_react105.useState)(null);
126114
+ const [showHelp, setShowHelp] = (0, import_react105.useState)(false);
126115
+ const [showTokenInput, setShowTokenInput] = (0, import_react105.useState)(false);
125618
126116
  const { activePanel, setActivePanel } = useActivePanel({
125619
126117
  hasSelection: currentScreen.type === "detail"
125620
126118
  });
125621
126119
  const { isInputActive } = useInputFocus();
125622
- const { selectedIndex: sidebarIndex } = useListNavigation({
125623
- itemCount: SIDEBAR_ITEMS.length,
125624
- viewportHeight: SIDEBAR_ITEMS.length,
126120
+ const { collapsedSections, toggleSection, navigableEntries } = useSidebarSections();
126121
+ const { selectedIndex: navIndex } = useListNavigation({
126122
+ itemCount: navigableEntries.length,
126123
+ viewportHeight: navigableEntries.length,
125625
126124
  isActive: activePanel === "sidebar" && !showHelp && !showTokenInput
125626
126125
  });
125627
- import_react102.default.useEffect(() => {
126126
+ const currentEntry = navigableEntries[navIndex];
126127
+ const sidebarIndex = currentEntry ? getItemIndex(currentEntry) ?? 0 : 0;
126128
+ const { isUnread } = useReadState();
126129
+ const sidebarCounts = useSidebarCounts(isUnread);
126130
+ import_react105.default.useEffect(() => {
125628
126131
  if (!loading && !isAuthenticated && !showTokenInput) {
125629
126132
  setShowTokenInput(true);
125630
126133
  } else if (isAuthenticated && showTokenInput) {
125631
126134
  setShowTokenInput(false);
125632
126135
  }
125633
126136
  }, [loading, isAuthenticated, showTokenInput]);
125634
- const handleTokenSubmit = (0, import_react102.useCallback)(
126137
+ const handleTokenSubmit = (0, import_react105.useCallback)(
125635
126138
  async (token) => {
125636
126139
  try {
125637
126140
  setTokenError(null);
@@ -125661,12 +126164,16 @@ function AppContent({
125661
126164
  exit4();
125662
126165
  }
125663
126166
  } else if (key.return && activePanel === "sidebar") {
125664
- setActivePanel("list");
126167
+ if (currentEntry?.type === "section") {
126168
+ toggleSection(currentEntry.sectionName);
126169
+ } else {
126170
+ setActivePanel("list");
126171
+ }
125665
126172
  }
125666
126173
  },
125667
126174
  { isActive: !showTokenInput && !isInputActive }
125668
126175
  );
125669
- const handleSelectPR = (0, import_react102.useCallback)(
126176
+ const handleSelectPR = (0, import_react105.useCallback)(
125670
126177
  (pr, list, index) => {
125671
126178
  setCurrentScreen({
125672
126179
  type: "detail",
@@ -125677,10 +126184,10 @@ function AppContent({
125677
126184
  },
125678
126185
  []
125679
126186
  );
125680
- const handleBackToList = (0, import_react102.useCallback)(() => {
126187
+ const handleBackToList = (0, import_react105.useCallback)(() => {
125681
126188
  setCurrentScreen({ type: "list" });
125682
126189
  }, []);
125683
- const handleNavigatePR = (0, import_react102.useCallback)(
126190
+ const handleNavigatePR = (0, import_react105.useCallback)(
125684
126191
  (direction) => {
125685
126192
  if (currentScreen.type !== "detail") return;
125686
126193
  const { prList, prIndex } = currentScreen;
@@ -125735,19 +126242,35 @@ function AppContent({
125735
126242
  }
125736
126243
  const terminalHeight = stdout?.rows ?? 24;
125737
126244
  const repoPath = repoOwner && repoName ? `${repoOwner}/${repoName}` : void 0;
125738
- import_react102.default.useEffect(() => {
126245
+ import_react105.default.useEffect(() => {
125739
126246
  if (currentScreen.type !== "detail") {
125740
126247
  setScreenContext(sidebarIndex === 4 ? "settings" : "pr-list");
125741
126248
  }
125742
126249
  }, [currentScreen.type, sidebarIndex]);
125743
126250
  const screenContext = useScreenContext();
126251
+ const rateLimit = useRateLimit();
126252
+ const connectionStatus = !isAuthenticated ? "error" : rateLimit.remaining < 100 ? "rate-limited" : "connected";
126253
+ const screenNames = [
126254
+ "Involved",
126255
+ "My PRs",
126256
+ "For Review",
126257
+ "This Repo",
126258
+ "Settings"
126259
+ ];
126260
+ const currentScreenName = currentScreen.type === "list" ? screenNames[sidebarIndex] : screenNames[sidebarIndex];
126261
+ const prTitle = currentScreen.type === "detail" ? currentScreen.pr.title : void 0;
126262
+ const prNumber = currentScreen.type === "detail" ? currentScreen.pr.number : void 0;
125744
126263
  return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(Box_default, { flexDirection: "column", height: terminalHeight, children: [
125745
126264
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
125746
126265
  TopBar,
125747
126266
  {
125748
126267
  username: user?.login ?? "anonymous",
125749
126268
  provider: "github",
125750
- repoPath
126269
+ repoPath,
126270
+ screenName: currentScreenName,
126271
+ prTitle,
126272
+ prNumber,
126273
+ connectionStatus
125751
126274
  }
125752
126275
  ),
125753
126276
  /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(Box_default, { flexDirection: "row", flexGrow: 1, children: [
@@ -125756,7 +126279,11 @@ function AppContent({
125756
126279
  {
125757
126280
  selectedIndex: sidebarIndex,
125758
126281
  visible: sidebarVisible,
125759
- isActive: activePanel === "sidebar"
126282
+ isActive: activePanel === "sidebar",
126283
+ counts: sidebarCounts,
126284
+ collapsedSections,
126285
+ navigableEntries,
126286
+ navIndex
125760
126287
  }
125761
126288
  ),
125762
126289
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(MainPanel, { isActive: activePanel === "list", children: renderScreen() })
@@ -125782,6 +126309,12 @@ var queryClient = new QueryClient({
125782
126309
  }
125783
126310
  }
125784
126311
  });
126312
+ function GitLabUnsupportedScreen() {
126313
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(Box_default, { flexDirection: "column", padding: 2, children: [
126314
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Text, { color: "red", bold: true, children: "GitLab provider not yet supported" }),
126315
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Text, { children: 'Your config (~/.config/lazyreview/config.yaml) has provider set to "gitlab". Please change it to "github" or remove the provider field to use the default.' })
126316
+ ] });
126317
+ }
125785
126318
  function AppWithTheme({
125786
126319
  repoOwner,
125787
126320
  repoName
@@ -125789,6 +126322,9 @@ function AppWithTheme({
125789
126322
  const { config: config2 } = useConfig();
125790
126323
  const themeName = config2?.theme ?? "tokyo-night";
125791
126324
  const theme14 = getThemeByName(themeName);
126325
+ if (config2?.provider === "gitlab") {
126326
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ThemeProvider, { theme: theme14, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(GitLabUnsupportedScreen, {}) });
126327
+ }
125792
126328
  return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ThemeProvider, { theme: theme14, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ErrorBoundary2, { children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(AppContent, { repoOwner, repoName }) }) });
125793
126329
  }
125794
126330
  function App2({ repoOwner, repoName }) {
@@ -125820,18 +126356,18 @@ async function main() {
125820
126356
  const arg = process.argv[2];
125821
126357
  if (arg === "--version" || arg === "-v") {
125822
126358
  const { readFileSync: readFileSync4 } = await import("fs");
125823
- const { resolve, dirname: dirname2 } = await import("path");
126359
+ const { resolve, dirname: dirname3 } = await import("path");
125824
126360
  const { fileURLToPath } = await import("url");
125825
- const dir = dirname2(fileURLToPath(import.meta.url));
126361
+ const dir = dirname3(fileURLToPath(import.meta.url));
125826
126362
  const pkg = JSON.parse(readFileSync4(resolve(dir, "..", "package.json"), "utf-8"));
125827
126363
  console.log(pkg.version);
125828
126364
  process.exit(0);
125829
126365
  }
125830
126366
  if (arg === "--help" || arg === "-h") {
125831
126367
  const { readFileSync: readFileSync4 } = await import("fs");
125832
- const { resolve, dirname: dirname2 } = await import("path");
126368
+ const { resolve, dirname: dirname3 } = await import("path");
125833
126369
  const { fileURLToPath } = await import("url");
125834
- const dir = dirname2(fileURLToPath(import.meta.url));
126370
+ const dir = dirname3(fileURLToPath(import.meta.url));
125835
126371
  const pkg = JSON.parse(readFileSync4(resolve(dir, "..", "package.json"), "utf-8"));
125836
126372
  const version = pkg.version;
125837
126373
  const help = [