@kitlangton/ghui 0.3.2 → 0.3.3

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/README.md +13 -3
  2. package/dist/index.js +277 -240
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -67,10 +67,12 @@ You can also copy `.env.example` to `.env` and edit the values locally.
67
67
  - `esc`: return from expanded details, leave diff/comment mode, or close modal
68
68
  - `r`: refresh
69
69
  - `d`: view stacked diff for all changed files
70
- - `c`: enter or exit diff comment mode while viewing a diff
71
- - `up` / `down` / `pageup` / `pagedown`: move comment target while in diff comment mode
70
+ - `shift-r`: review or approve the selected pull request
71
+ - `up` / `down` / `pageup` / `pagedown`: move comment target while viewing a diff
72
72
  - `enter`: open a commented diff line, or start a comment on an uncommented line
73
- - `a`: add a comment while in diff comment mode
73
+ - `v`: start or clear a multi-line diff comment range
74
+ - `n` / `p`: jump between diff comment threads
75
+ - `f`: open the changed-files navigator while viewing a diff
74
76
  - `left` / `right`: choose the deleted or added side while in split diff comment mode
75
77
  - `[` / `]`: switch files while viewing or commenting on a diff
76
78
  - `s`: toggle draft or ready-for-review state
@@ -81,3 +83,11 @@ You can also copy `.env.example` to `.env` and edit the values locally.
81
83
  - `o`: open PR in browser
82
84
  - `y`: copy PR metadata
83
85
  - `q`: quit
86
+
87
+ Review submission:
88
+
89
+ - Press `shift-r` to open the review modal.
90
+ - Use `j` / `k` or `up` / `down` to choose Comment, Approve, or Request changes.
91
+ - Press `enter` to move to the optional summary area.
92
+ - Press `enter` again to submit, or `shift-enter` to insert a newline.
93
+ - Press `esc` from the summary to return to action selection; press `esc` from action selection to cancel.
package/dist/index.js CHANGED
@@ -1149,7 +1149,7 @@ var Detail, detailViewKeymap;
1149
1149
  var init_detailView = __esm(() => {
1150
1150
  init_src();
1151
1151
  Detail = context();
1152
- detailViewKeymap = Detail(scrollCommands(), { id: "detail.close", title: "Close detail", keys: ["escape", "return"], run: (s) => s.closeDetail() }, { id: "detail.theme", title: "Open theme", keys: ["t"], run: (s) => s.openTheme() }, { id: "detail.diff", title: "Open diff", keys: ["d"], run: (s) => s.openDiff() }, { id: "detail.close-pr", title: "Close pull request", keys: ["x"], run: (s) => s.closePullRequest() }, { id: "detail.labels", title: "Manage labels", keys: ["l"], run: (s) => s.openLabels() }, { id: "detail.merge", title: "Merge", keys: ["m", "shift+m"], run: (s) => s.openMerge() }, { id: "detail.toggle-draft", title: "Toggle draft", keys: ["s", "shift+s"], run: (s) => s.toggleDraft() }, { id: "detail.refresh", title: "Refresh", keys: ["r"], run: (s) => s.refresh() }, { id: "detail.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.openInBrowser() }, { id: "detail.copy", title: "Copy metadata", keys: ["y"], run: (s) => s.copyMetadata() });
1152
+ detailViewKeymap = Detail(scrollCommands(), { id: "detail.close", title: "Close detail", keys: ["escape", "return"], run: (s) => s.closeDetail() }, { id: "detail.theme", title: "Open theme", keys: ["t"], run: (s) => s.openTheme() }, { id: "detail.diff", title: "Open diff", keys: ["d"], run: (s) => s.openDiff() }, { id: "detail.review", title: "Review pull request", keys: ["shift+r"], run: (s) => s.openReview() }, { id: "detail.close-pr", title: "Close pull request", keys: ["x"], run: (s) => s.closePullRequest() }, { id: "detail.labels", title: "Manage labels", keys: ["l"], run: (s) => s.openLabels() }, { id: "detail.merge", title: "Merge", keys: ["m", "shift+m"], run: (s) => s.openMerge() }, { id: "detail.toggle-draft", title: "Toggle draft", keys: ["s", "shift+s"], run: (s) => s.toggleDraft() }, { id: "detail.refresh", title: "Refresh", keys: ["r"], run: (s) => s.refresh() }, { id: "detail.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.openInBrowser() }, { id: "detail.copy", title: "Copy metadata", keys: ["y"], run: (s) => s.copyMetadata() });
1153
1153
  });
1154
1154
 
1155
1155
  // src/keymap/helpers.ts
@@ -1187,7 +1187,7 @@ var init_diffView = __esm(() => {
1187
1187
  title: "Jump down",
1188
1188
  keys: ["shift+down", "shift+j", "meta+down", "meta+j"],
1189
1189
  run: (s) => s.moveAnchor(8)
1190
- }, ...countedVerticalBindings((s, delta) => s.moveAnchor(delta)), { id: "diff.up", title: "Up", keys: ["up", "k"], run: (s) => s.moveAnchor(-1) }, { id: "diff.down", title: "Down", keys: ["down", "j"], run: (s) => s.moveAnchor(1) }, { id: "diff.side-left", title: "Old side", keys: ["left", "h"], run: (s) => s.selectSide("LEFT") }, { id: "diff.side-right", title: "New side", keys: ["right", "l"], run: (s) => s.selectSide("RIGHT") }, { id: "diff.changed-files", title: "Changed files", keys: ["f"], run: (s) => s.openChangedFiles() }, { id: "diff.next-file", title: "Next file", keys: ["]"], run: (s) => s.nextFile() }, { id: "diff.previous-file", title: "Previous file", keys: ["["], run: (s) => s.previousFile() }, { id: "diff.submit-review", title: "Submit review", keys: ["shift+r"], run: (s) => s.openSubmitReview() }, { id: "diff.first", title: "First comment", keys: ["g g"], run: (s) => s.moveAnchorToBoundary("first") }, { id: "diff.last", title: "Last comment", keys: ["shift+g"], run: (s) => s.moveAnchorToBoundary("last") }, { id: "diff.align-center", title: "Align center", keys: ["z z"], run: (s) => s.alignAnchor("center") }, { id: "diff.align-top", title: "Align top", keys: ["z t"], run: (s) => s.alignAnchor("top") }, { id: "diff.align-bottom", title: "Align bottom", keys: ["z b"], run: (s) => s.alignAnchor("bottom") }, { id: "diff.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.openInBrowser() });
1190
+ }, ...countedVerticalBindings((s, delta) => s.moveAnchor(delta)), { id: "diff.up", title: "Up", keys: ["up", "k"], run: (s) => s.moveAnchor(-1) }, { id: "diff.down", title: "Down", keys: ["down", "j"], run: (s) => s.moveAnchor(1) }, { id: "diff.side-left", title: "Old side", keys: ["left", "h"], run: (s) => s.selectSide("LEFT") }, { id: "diff.side-right", title: "New side", keys: ["right", "l"], run: (s) => s.selectSide("RIGHT") }, { id: "diff.changed-files", title: "Changed files", keys: ["f"], run: (s) => s.openChangedFiles() }, { id: "diff.next-file", title: "Next file", keys: ["]"], run: (s) => s.nextFile() }, { id: "diff.previous-file", title: "Previous file", keys: ["["], run: (s) => s.previousFile() }, { id: "diff.submit-review", title: "Review pull request", keys: ["shift+r"], run: (s) => s.openSubmitReview() }, { id: "diff.first", title: "First comment", keys: ["g g"], run: (s) => s.moveAnchorToBoundary("first") }, { id: "diff.last", title: "Last comment", keys: ["shift+g"], run: (s) => s.moveAnchorToBoundary("last") }, { id: "diff.align-center", title: "Align center", keys: ["z z"], run: (s) => s.alignAnchor("center") }, { id: "diff.align-top", title: "Align top", keys: ["z t"], run: (s) => s.alignAnchor("top") }, { id: "diff.align-bottom", title: "Align bottom", keys: ["z b"], run: (s) => s.alignAnchor("bottom") }, { id: "diff.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.openInBrowser() });
1191
1191
  });
1192
1192
 
1193
1193
  // src/keymap/filterMode.ts
@@ -1211,7 +1211,7 @@ var List, listNavKeymap;
1211
1211
  var init_listNav = __esm(() => {
1212
1212
  init_src();
1213
1213
  List = context();
1214
- listNavKeymap = List({ id: "list.filter", title: "Filter", keys: ["/"], run: (s) => s.runCommandById("filter.open") }, { id: "list.refresh", title: "Refresh", keys: ["r"], run: (s) => s.runCommandById("pull.refresh") }, { id: "list.theme", title: "Theme", keys: ["t"], run: (s) => s.runCommandById("theme.open") }, { id: "list.diff", title: "Open diff", keys: ["d"], run: (s) => s.runCommandById("diff.open") }, { id: "list.labels", title: "Labels", keys: ["l"], run: (s) => s.runCommandById("pull.labels") }, { id: "list.merge", title: "Merge", keys: ["m", "shift+m"], run: (s) => s.runCommandById("pull.merge") }, { id: "list.close-pr", title: "Close PR", keys: ["x"], run: (s) => s.runCommandById("pull.close") }, { id: "list.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.runCommandById("pull.open-browser") }, { id: "list.toggle-draft", title: "Toggle draft", keys: ["s", "shift+s"], run: (s) => s.runCommandById("pull.toggle-draft") }, { id: "list.copy", title: "Copy metadata", keys: ["y"], run: (s) => s.runCommandById("pull.copy-metadata") }, { id: "list.detail.open", title: "Open details", keys: ["return"], run: (s) => s.runCommandById("detail.open") }, { id: "list.next-tab", title: "Next view", keys: ["tab"], run: (s) => s.switchQueueMode(1) }, { id: "list.prev-tab", title: "Previous view", keys: ["shift+tab"], run: (s) => s.switchQueueMode(-1) }, {
1214
+ listNavKeymap = List({ id: "list.filter", title: "Filter", keys: ["/"], run: (s) => s.runCommandById("filter.open") }, { id: "list.refresh", title: "Refresh", keys: ["r"], run: (s) => s.runCommandById("pull.refresh") }, { id: "list.theme", title: "Theme", keys: ["t"], run: (s) => s.runCommandById("theme.open") }, { id: "list.diff", title: "Open diff", keys: ["d"], run: (s) => s.runCommandById("diff.open") }, { id: "list.review", title: "Review pull request", keys: ["shift+r"], run: (s) => s.runCommandById("pull.submit-review") }, { id: "list.labels", title: "Labels", keys: ["l"], run: (s) => s.runCommandById("pull.labels") }, { id: "list.merge", title: "Merge", keys: ["m", "shift+m"], run: (s) => s.runCommandById("pull.merge") }, { id: "list.close-pr", title: "Close PR", keys: ["x"], run: (s) => s.runCommandById("pull.close") }, { id: "list.open-browser", title: "Open in browser", keys: ["o"], run: (s) => s.runCommandById("pull.open-browser") }, { id: "list.toggle-draft", title: "Toggle draft", keys: ["s", "shift+s"], run: (s) => s.runCommandById("pull.toggle-draft") }, { id: "list.copy", title: "Copy metadata", keys: ["y"], run: (s) => s.runCommandById("pull.copy-metadata") }, { id: "list.detail.open", title: "Open details", keys: ["return"], run: (s) => s.runCommandById("detail.open") }, { id: "list.next-tab", title: "Next view", keys: ["tab"], run: (s) => s.switchQueueMode(1) }, { id: "list.prev-tab", title: "Previous view", keys: ["shift+tab"], run: (s) => s.switchQueueMode(-1) }, {
1215
1215
  id: "list.clear-filter",
1216
1216
  title: "Clear filter",
1217
1217
  keys: ["escape"],
@@ -1291,7 +1291,7 @@ var SubmitReview, submitReviewModalKeymap;
1291
1291
  var init_submitReviewModal = __esm(() => {
1292
1292
  init_src();
1293
1293
  SubmitReview = context();
1294
- submitReviewModalKeymap = SubmitReview({ id: "submit-review.escape", title: "Cancel", keys: ["escape"], run: (s) => s.closeModal() }, { id: "submit-review.submit", title: "Submit", keys: ["ctrl+s", "return"], run: (s) => s.submit() }, { id: "submit-review.newline", title: "Insert newline", keys: ["shift+return"], run: (s) => s.insertNewline() }, { id: "submit-review.next-action", title: "Next action", keys: ["tab"], run: (s) => s.moveActionSelection(1) }, { id: "submit-review.previous-action", title: "Previous action", keys: ["shift+tab"], run: (s) => s.moveActionSelection(-1) }, { id: "submit-review.move-left", title: "Cursor left", keys: ["left", "ctrl+b"], run: (s) => s.moveLeft() }, { id: "submit-review.move-right", title: "Cursor right", keys: ["right", "ctrl+f"], run: (s) => s.moveRight() }, { id: "submit-review.move-up", title: "Cursor up", keys: ["up"], run: (s) => s.moveUp() }, { id: "submit-review.move-down", title: "Cursor down", keys: ["down"], run: (s) => s.moveDown() }, { id: "submit-review.line-start", title: "Line start", keys: ["home", "ctrl+a"], run: (s) => s.moveLineStart() }, { id: "submit-review.line-end", title: "Line end", keys: ["end", "ctrl+e"], run: (s) => s.moveLineEnd() }, { id: "submit-review.word-back", title: "Word backward", keys: ["meta+b", "meta+left"], run: (s) => s.moveWordBackward() }, { id: "submit-review.word-forward", title: "Word forward", keys: ["meta+f", "meta+right"], run: (s) => s.moveWordForward() }, { id: "submit-review.backspace", title: "Backspace", keys: ["backspace"], run: (s) => s.backspace() }, { id: "submit-review.delete", title: "Delete", keys: ["delete", "ctrl+d"], run: (s) => s.deleteForward() }, { id: "submit-review.delete-word-back", title: "Delete word backward", keys: ["ctrl+w", "meta+backspace"], run: (s) => s.deleteWordBackward() }, { id: "submit-review.delete-word-forward", title: "Delete word forward", keys: ["meta+delete"], run: (s) => s.deleteWordForward() }, { id: "submit-review.delete-to-line-start", title: "Delete to line start", keys: ["ctrl+u"], run: (s) => s.deleteToLineStart() }, { id: "submit-review.delete-to-line-end", title: "Delete to line end", keys: ["ctrl+k"], run: (s) => s.deleteToLineEnd() });
1294
+ submitReviewModalKeymap = SubmitReview({ id: "submit-review.escape", title: "Back / cancel", keys: ["escape"], run: (s) => s.handleEscape() }, { id: "submit-review.focus-summary", title: "Edit summary", keys: ["return"], when: (s) => !s.summaryFocused, run: (s) => s.focusSummary() }, { id: "submit-review.submit", title: "Submit", keys: ["return"], when: (s) => s.summaryFocused, run: (s) => s.submit() }, { id: "submit-review.newline", title: "Insert newline", keys: ["shift+return"], when: (s) => s.summaryFocused, run: (s) => s.insertNewline() }, { id: "submit-review.next-action", title: "Next action", keys: ["down", "j"], when: (s) => !s.summaryFocused, run: (s) => s.moveActionSelection(1) }, { id: "submit-review.previous-action", title: "Previous action", keys: ["up", "k"], when: (s) => !s.summaryFocused, run: (s) => s.moveActionSelection(-1) }, { id: "submit-review.move-left", title: "Cursor left", keys: ["left", "ctrl+b"], when: (s) => s.summaryFocused, run: (s) => s.moveLeft() }, { id: "submit-review.move-right", title: "Cursor right", keys: ["right", "ctrl+f"], when: (s) => s.summaryFocused, run: (s) => s.moveRight() }, { id: "submit-review.move-up", title: "Cursor up", keys: ["up"], when: (s) => s.summaryFocused, run: (s) => s.moveUp() }, { id: "submit-review.move-down", title: "Cursor down", keys: ["down"], when: (s) => s.summaryFocused, run: (s) => s.moveDown() }, { id: "submit-review.line-start", title: "Line start", keys: ["home", "ctrl+a"], when: (s) => s.summaryFocused, run: (s) => s.moveLineStart() }, { id: "submit-review.line-end", title: "Line end", keys: ["end", "ctrl+e"], when: (s) => s.summaryFocused, run: (s) => s.moveLineEnd() }, { id: "submit-review.word-back", title: "Word backward", keys: ["meta+b", "meta+left"], when: (s) => s.summaryFocused, run: (s) => s.moveWordBackward() }, { id: "submit-review.word-forward", title: "Word forward", keys: ["meta+f", "meta+right"], when: (s) => s.summaryFocused, run: (s) => s.moveWordForward() }, { id: "submit-review.backspace", title: "Backspace", keys: ["backspace"], when: (s) => s.summaryFocused, run: (s) => s.backspace() }, { id: "submit-review.delete", title: "Delete", keys: ["delete", "ctrl+d"], when: (s) => s.summaryFocused, run: (s) => s.deleteForward() }, { id: "submit-review.delete-word-back", title: "Delete word backward", keys: ["ctrl+w", "meta+backspace"], when: (s) => s.summaryFocused, run: (s) => s.deleteWordBackward() }, { id: "submit-review.delete-word-forward", title: "Delete word forward", keys: ["meta+delete"], when: (s) => s.summaryFocused, run: (s) => s.deleteWordForward() }, { id: "submit-review.delete-to-line-start", title: "Delete to line start", keys: ["ctrl+u"], when: (s) => s.summaryFocused, run: (s) => s.deleteToLineStart() }, { id: "submit-review.delete-to-line-end", title: "Delete to line end", keys: ["ctrl+k"], when: (s) => s.summaryFocused, run: (s) => s.deleteToLineEnd() });
1295
1295
  });
1296
1296
 
1297
1297
  // src/keymap/themeModal.ts
@@ -1400,13 +1400,7 @@ var SCOPE_ORDER, sortCommandsByScope = (commands) => [...commands].sort((left, r
1400
1400
  return true;
1401
1401
  }
1402
1402
  return query.length === 0;
1403
- }, commandSearchText = (command2) => normalize([
1404
- command2.title,
1405
- command2.subtitle,
1406
- command2.scope,
1407
- command2.shortcut,
1408
- ...command2.keywords ?? []
1409
- ].filter(Boolean).join(" ")), commandScore = (command2, query) => {
1403
+ }, commandSearchText = (command2) => normalize([command2.title, command2.subtitle, command2.scope, command2.shortcut, ...command2.keywords ?? []].filter(Boolean).join(" ")), commandScore = (command2, query) => {
1410
1404
  const normalizedQuery = normalize(query);
1411
1405
  if (normalizedQuery.length === 0)
1412
1406
  return 0;
@@ -1470,10 +1464,7 @@ var init_domain = __esm(() => {
1470
1464
  // src/pullRequestViews.ts
1471
1465
  var initialPullRequestView = () => ({ _tag: "Queue", mode: "authored", repository: null }), viewMode = (view) => view._tag === "Repository" ? "repository" : view.mode, viewRepository = (view) => view.repository, viewCacheKey = (view) => view._tag === "Repository" ? `repository:${view.repository}` : view.mode, viewEquals = (left, right) => left._tag === right._tag && viewMode(left) === viewMode(right) && left.repository === right.repository, activePullRequestViews = (view) => {
1472
1466
  const repository = viewRepository(view);
1473
- return [
1474
- ...repository ? [{ _tag: "Repository", repository }] : [],
1475
- ...pullRequestQueueModes.map((mode) => ({ _tag: "Queue", mode, repository }))
1476
- ];
1467
+ return [...repository ? [{ _tag: "Repository", repository }] : [], ...pullRequestQueueModes.map((mode) => ({ _tag: "Queue", mode, repository }))];
1477
1468
  }, nextView = (view, views, delta) => {
1478
1469
  const index = Math.max(0, views.findIndex((candidate) => viewEquals(candidate, view)));
1479
1470
  return views[(index + delta + views.length) % views.length];
@@ -1528,7 +1519,6 @@ var buildAppCommands = ({
1528
1519
  const selectedDiffLineReason = diffFullView && diffReady ? selectedDiffCommentAnchorLabel ? null : "No diff line selected." : diffOpenReadyReason;
1529
1520
  const diffThreadReason = diffFullView && diffReady ? hasDiffCommentThreads ? null : "No diff comments loaded." : diffOpenReadyReason;
1530
1521
  const changedFilesReason = diffFullView && diffReady ? readyDiffFileCount > 0 ? null : "No changed files loaded." : diffOpenReadyReason;
1531
- const submitReviewReason = diffFullView && diffReady ? noOpenPullRequestReason : diffOpenReadyReason;
1532
1522
  const loadMoreDisabledReason = isLoadingMorePullRequests ? "Already loading more pull requests." : hasMorePullRequests ? null : "No more pull requests loaded by this view.";
1533
1523
  const forSelected = (command2) => {
1534
1524
  const { requireOpen, ...rest } = command2;
@@ -1757,15 +1747,14 @@ var buildAppCommands = ({
1757
1747
  keywords: ["review", "reply"],
1758
1748
  run: actions.openDiffCommentModal
1759
1749
  }),
1760
- defineCommand({
1761
- id: "diff.submit-review",
1762
- title: "Submit pull request review",
1763
- scope: "Diff",
1764
- subtitle: selectedPullRequestLabel,
1765
- shortcut: "R",
1766
- disabledReason: submitReviewReason,
1767
- keywords: ["review", "approve", "request changes"],
1768
- run: actions.openSubmitReviewModal
1750
+ forSelected({
1751
+ id: "pull.submit-review",
1752
+ title: "Review pull request",
1753
+ scope: "Pull request",
1754
+ shortcut: "shift-r",
1755
+ requireOpen: true,
1756
+ keywords: ["review", "approve", "request changes", "comment"],
1757
+ run: () => actions.openSubmitReviewModal("APPROVE")
1769
1758
  }),
1770
1759
  forSelected({
1771
1760
  id: "pull.toggle-draft",
@@ -2087,11 +2076,7 @@ var init_Clipboard = __esm(() => {
2087
2076
  detail: Schema3.String
2088
2077
  }) {
2089
2078
  };
2090
- clipboardCommands = process.platform === "darwin" ? [["pbcopy"]] : process.platform === "linux" ? [
2091
- ...process.env.WAYLAND_DISPLAY ? [["wl-copy"]] : [],
2092
- ["xclip", "-selection", "clipboard"],
2093
- ["xsel", "--clipboard", "--input"]
2094
- ] : [];
2079
+ clipboardCommands = process.platform === "darwin" ? [["pbcopy"]] : process.platform === "linux" ? [...process.env.WAYLAND_DISPLAY ? [["wl-copy"]] : [], ["xclip", "-selection", "clipboard"], ["xsel", "--clipboard", "--input"]] : [];
2095
2080
  installHint = process.platform === "linux" ? " Install wl-clipboard, xclip, or xsel." : "";
2096
2081
  unavailableDetail = `Clipboard is not available.${installHint}`;
2097
2082
  Clipboard = class Clipboard extends Context3.Service()("ghui/Clipboard") {
@@ -2397,14 +2382,8 @@ var init_GitHubService = __esm(() => {
2397
2382
  status: OptionalNullableString,
2398
2383
  patch: OptionalNullableString
2399
2384
  });
2400
- CommentsResponseSchema = Schema4.Union([
2401
- Schema4.Array(PullRequestCommentSchema),
2402
- Schema4.Array(Schema4.Array(PullRequestCommentSchema))
2403
- ]);
2404
- PullRequestFilesResponseSchema = Schema4.Union([
2405
- Schema4.Array(PullRequestFileSchema),
2406
- Schema4.Array(Schema4.Array(PullRequestFileSchema))
2407
- ]);
2385
+ CommentsResponseSchema = Schema4.Union([Schema4.Array(PullRequestCommentSchema), Schema4.Array(Schema4.Array(PullRequestCommentSchema))]);
2386
+ PullRequestFilesResponseSchema = Schema4.Union([Schema4.Array(PullRequestFileSchema), Schema4.Array(Schema4.Array(PullRequestFileSchema))]);
2408
2387
  RepoLabelsResponseSchema = Schema4.Array(Schema4.Struct({
2409
2388
  name: Schema4.String,
2410
2389
  color: Schema4.String
@@ -2615,26 +2594,11 @@ query RepositoryPullRequests($owner: String!, $name: String!, $first: Int!, $aft
2615
2594
  return parsePullRequest(pullRequest);
2616
2595
  });
2617
2596
  const getAuthenticatedUser = () => ghJson("getAuthenticatedUser", ViewerSchema, ["api", "user"]).pipe(Effect6.map((viewer) => viewer.login));
2618
- const getPullRequestDiff = (repository, number) => ghJson("getPullRequestDiff", PullRequestFilesResponseSchema, [
2619
- "api",
2620
- "--paginate",
2621
- "--slurp",
2622
- `repos/${repository}/pulls/${number}/files`
2623
- ]).pipe(Effect6.map((response) => pullRequestFilesToPatch(parsePullRequestFiles(response))));
2624
- const listPullRequestComments = (repository, number) => ghJson("listPullRequestComments", CommentsResponseSchema, [
2625
- "api",
2626
- "--paginate",
2627
- "--slurp",
2628
- `repos/${repository}/pulls/${number}/comments`
2629
- ]).pipe(Effect6.map(parsePullRequestComments));
2597
+ const getPullRequestDiff = (repository, number) => ghJson("getPullRequestDiff", PullRequestFilesResponseSchema, ["api", "--paginate", "--slurp", `repos/${repository}/pulls/${number}/files`]).pipe(Effect6.map((response) => pullRequestFilesToPatch(parsePullRequestFiles(response))));
2598
+ const listPullRequestComments = (repository, number) => ghJson("listPullRequestComments", CommentsResponseSchema, ["api", "--paginate", "--slurp", `repos/${repository}/pulls/${number}/comments`]).pipe(Effect6.map(parsePullRequestComments));
2630
2599
  const listPullRequestConversation = Effect6.fn("GitHubService.listPullRequestConversation")(function* (repository, number) {
2631
2600
  const [issueComments, reviewComments] = yield* Effect6.all([
2632
- ghJson("listPullRequestIssueComments", CommentsResponseSchema, [
2633
- "api",
2634
- "--paginate",
2635
- "--slurp",
2636
- `repos/${repository}/issues/${number}/comments`
2637
- ]).pipe(Effect6.map(parseIssueComments)),
2601
+ ghJson("listPullRequestIssueComments", CommentsResponseSchema, ["api", "--paginate", "--slurp", `repos/${repository}/issues/${number}/comments`]).pipe(Effect6.map(parseIssueComments)),
2638
2602
  listPullRequestComments(repository, number).pipe(Effect6.map((comments) => comments.map(reviewCommentConversationItem)))
2639
2603
  ], { concurrency: "unbounded" });
2640
2604
  return sortConversationItems([...issueComments, ...reviewComments]);
@@ -2685,27 +2649,9 @@ query RepositoryPullRequests($owner: String!, $name: String!, $first: Int!, $aft
2685
2649
  ]);
2686
2650
  return parsePullRequestComment(response) ?? fallbackCreatedComment(input);
2687
2651
  });
2688
- const submitPullRequestReview = (input) => ghVoid("submitPullRequestReview", [
2689
- "pr",
2690
- "review",
2691
- String(input.number),
2692
- "--repo",
2693
- input.repository,
2694
- REVIEW_EVENT_CLI_FLAG[input.event],
2695
- "--body",
2696
- input.body
2697
- ]);
2652
+ const submitPullRequestReview = (input) => ghVoid("submitPullRequestReview", ["pr", "review", String(input.number), "--repo", input.repository, REVIEW_EVENT_CLI_FLAG[input.event], "--body", input.body]);
2698
2653
  const toggleDraftStatus = (repository, number, isDraft) => ghVoid("toggleDraftStatus", ["pr", "ready", String(number), "--repo", repository, ...isDraft ? [] : ["--undo"]]);
2699
- const listRepoLabels = (repository) => ghJson("listRepoLabels", RepoLabelsResponseSchema, [
2700
- "label",
2701
- "list",
2702
- "--repo",
2703
- repository,
2704
- "--json",
2705
- "name,color",
2706
- "--limit",
2707
- "100"
2708
- ]).pipe(Effect6.map((labels) => labels.map((label) => ({ name: label.name, color: `#${label.color}` }))));
2654
+ const listRepoLabels = (repository) => ghJson("listRepoLabels", RepoLabelsResponseSchema, ["label", "list", "--repo", repository, "--json", "name,color", "--limit", "100"]).pipe(Effect6.map((labels) => labels.map((label) => ({ name: label.name, color: `#${label.color}` }))));
2709
2655
  const addPullRequestLabel = (repository, number, label) => ghVoid("addPullRequestLabel", ["pr", "edit", String(number), "--repo", repository, "--add-label", label]);
2710
2656
  const removePullRequestLabel = (repository, number, label) => ghVoid("removePullRequestLabel", ["pr", "edit", String(number), "--repo", repository, "--remove-label", label]);
2711
2657
  return GitHubService.of({
@@ -3025,10 +2971,7 @@ var DiffView, DiffWrapMode, DiffWhitespaceMode, DiffCommentKind, PullRequestDiff
3025
2971
  }
3026
2972
  return { additions, deletions };
3027
2973
  }, diffFileStatsText = (stats) => {
3028
- return [
3029
- stats.additions > 0 ? `+${stats.additions}` : null,
3030
- stats.deletions > 0 ? `-${stats.deletions}` : null
3031
- ].filter((part) => part !== null).join(" ");
2974
+ return [stats.additions > 0 ? `+${stats.additions}` : null, stats.deletions > 0 ? `-${stats.deletions}` : null].filter((part) => part !== null).join(" ");
3032
2975
  }, getDiffCommentAnchors = (file, view = "unified", wrapMode = "none", width = 120) => {
3033
2976
  const anchors = [];
3034
2977
  const lines = file.patch.split(`
@@ -3386,7 +3329,13 @@ var fitCell = (text, width, align = "left") => {
3386
3329
  fg,
3387
3330
  children
3388
3331
  }, undefined, false, undefined, this)
3389
- }, undefined, false, undefined, this), MatchedCell = ({ text, width, query, align = "left", matchIndexes }) => {
3332
+ }, undefined, false, undefined, this), MatchedCell = ({
3333
+ text,
3334
+ width,
3335
+ query,
3336
+ align = "left",
3337
+ matchIndexes
3338
+ }) => {
3390
3339
  const fitted = fitCell(text, width, align);
3391
3340
  if (matchIndexes && matchIndexes.length > 0) {
3392
3341
  const highlighted = new Set(matchIndexes.filter((index2) => index2 >= 0 && index2 < fitted.length));
@@ -3817,16 +3766,9 @@ var commentCountText = (count) => count === 1 ? "1 comment" : `${count} comments
3817
3766
  for (const group of groups)
3818
3767
  appendMetaGroup(segments, group);
3819
3768
  return segments;
3820
- }, commentBodyRows = ({
3821
- keyPrefix,
3822
- body,
3823
- width
3824
- }) => wrapCommentText(body, Math.max(1, width - 2)).map((line, index) => ({
3769
+ }, commentBodyRows = ({ keyPrefix, body, width }) => wrapCommentText(body, Math.max(1, width - 2)).map((line, index) => ({
3825
3770
  key: `${keyPrefix}:body:${index}`,
3826
- segments: [
3827
- { text: "\u2502 ", fg: colors.muted },
3828
- ...inlineCommentSegments(line)
3829
- ]
3771
+ segments: [{ text: "\u2502 ", fg: colors.muted }, ...inlineCommentSegments(line)]
3830
3772
  })), commentDisplayRows = ({
3831
3773
  item,
3832
3774
  width,
@@ -4139,20 +4081,18 @@ var DETAIL_BODY_LINES = 6, DETAIL_PLACEHOLDER_ROWS = 4, DETAIL_BODY_SCROLL_LIMIT
4139
4081
  if (item._tag !== "review-comment")
4140
4082
  return [];
4141
4083
  const pathWidth = Math.max(12, width - item.author.length - 20);
4142
- return [[
4143
- { text: truncateConversationPath(item.path, pathWidth), fg: colors.inlineCode }
4144
- ]];
4084
+ return [[{ text: truncateConversationPath(item.path, pathWidth), fg: colors.inlineCode }]];
4145
4085
  }, conversationPreview = ({
4146
4086
  items,
4147
4087
  status,
4148
4088
  width,
4149
4089
  limit
4150
4090
  }) => {
4151
- if (status === "idle" || status === "ready" && items.length === 0 || limit <= 0)
4091
+ if (status !== "ready" || items.length === 0 || limit <= 0)
4152
4092
  return [];
4153
4093
  const rows = [];
4154
4094
  const title = "Conversation";
4155
- const countText = status === "loading" ? "loading" : commentCountText(items.length);
4095
+ const countText = commentCountText(items.length);
4156
4096
  const gap = Math.max(2, width - title.length - countText.length);
4157
4097
  rows.push({
4158
4098
  segments: [
@@ -4161,10 +4101,6 @@ var DETAIL_BODY_LINES = 6, DETAIL_PLACEHOLDER_ROWS = 4, DETAIL_BODY_SCROLL_LIMIT
4161
4101
  { text: countText, fg: colors.muted }
4162
4102
  ]
4163
4103
  });
4164
- if (items.length === 0) {
4165
- rows.push({ segments: [{ text: "\u2502 ", fg: colors.muted }, { text: "Loading comments...", fg: colors.muted }] });
4166
- return rows.slice(0, limit);
4167
- }
4168
4104
  for (const item of items) {
4169
4105
  if (rows.length >= limit)
4170
4106
  break;
@@ -4187,11 +4123,7 @@ var DETAIL_BODY_LINES = 6, DETAIL_PLACEHOLDER_ROWS = 4, DETAIL_BODY_SCROLL_LIMIT
4187
4123
  });
4188
4124
  if (conversationRows.length === 0)
4189
4125
  return summaryRows;
4190
- return [
4191
- ...summaryRows,
4192
- previewDivider(),
4193
- ...conversationRows
4194
- ].slice(0, limit);
4126
+ return [...summaryRows, previewDivider(), ...conversationRows].slice(0, limit);
4195
4127
  }, deduplicateChecks = (checks) => {
4196
4128
  const seen = new Map;
4197
4129
  for (const check of checks) {
@@ -4683,40 +4615,28 @@ var RetryProgress, initialRetryProgress, filterEditingHints, diffViewHints = (ct
4683
4615
  { key: "\u2191\u2193", label: ctx.diffRangeActive ? "range" : "line" },
4684
4616
  { key: "enter", label: ctx.diffRangeActive ? "comment" : "open" },
4685
4617
  { key: "v", label: ctx.diffRangeActive ? "clear" : "range" },
4686
- { key: "n/p", label: "threads" },
4687
4618
  { key: "[]", label: "files" },
4688
- { key: "V", label: "view" },
4689
- { key: "w", label: "wrap" },
4690
- { key: "r", label: "reload" },
4691
- { key: "o", label: "open" }
4619
+ { key: "r", label: "reload" }
4692
4620
  ], detailFullViewHints = (ctx) => [
4693
4621
  { key: "esc", label: "back" },
4694
4622
  { key: "\u2191\u2193", label: "scroll" },
4695
4623
  { key: "r", label: ctx.hasError ? "retry" : "refresh" },
4696
- { key: "t", label: "theme" },
4697
- { key: "s", label: "state", when: ctx.hasSelection },
4698
- { key: "d", label: "diff", when: ctx.hasSelection },
4699
- { key: "l", label: "labels", when: ctx.hasSelection },
4700
- { key: "m", label: "merge", when: ctx.hasSelection },
4701
- { key: "x", label: "close", when: ctx.hasSelection && ctx.canCloseSelection },
4702
- { key: "o", label: "open" },
4703
- { key: "y", label: "copy" },
4704
- { key: "q", label: "quit" }
4624
+ { key: "d", label: "diff", when: ctx.hasSelection }
4705
4625
  ], defaultHints = (ctx) => {
4706
4626
  const retrying = ctx.retryProgress._tag === "Retrying";
4707
4627
  return [
4708
4628
  { key: "/", label: "filter" },
4709
- { key: "t", label: "theme" },
4710
4629
  { key: "esc", label: "clear", when: ctx.showFilterClear },
4711
- { key: "retry", label: retrying ? `${ctx.retryProgress.attempt}/${ctx.retryProgress.max}` : "", when: retrying, keyFg: colors.status.pending },
4630
+ {
4631
+ key: "retry",
4632
+ label: retrying ? `${ctx.retryProgress.attempt}/${ctx.retryProgress.max}` : "",
4633
+ when: retrying,
4634
+ keyFg: colors.status.pending
4635
+ },
4712
4636
  { key: ctx.loadingIndicator, label: "loading", when: !retrying && ctx.isLoading, keyFg: colors.status.pending },
4713
4637
  { key: "r", label: "retry", when: ctx.hasError },
4638
+ { key: "enter", label: "details", when: ctx.hasSelection },
4714
4639
  { key: "d", label: "diff", when: ctx.hasSelection },
4715
- { key: "l", label: "labels", when: ctx.hasSelection },
4716
- { key: "m", label: "merge", when: ctx.hasSelection },
4717
- { key: "x", label: "close", when: ctx.hasSelection && ctx.canCloseSelection },
4718
- { key: "o", label: "open", when: ctx.hasSelection },
4719
- { key: "y", label: "copy", when: ctx.hasSelection },
4720
4640
  { key: "ctrl-p", label: "commands" }
4721
4641
  ];
4722
4642
  }, footerHints = (ctx) => {
@@ -5018,7 +4938,11 @@ var scopeLabels, buildCommandPaletteRows = (commands) => {
5018
4938
  countText,
5019
4939
  onBodyMouseScroll: handleMouseScroll,
5020
4940
  footer: /* @__PURE__ */ jsxDEV7(HintRow, {
5021
- items: [{ key: "\u2191\u2193", label: "select" }, { key: "enter", label: "run" }, { key: "esc", label: "close" }]
4941
+ items: [
4942
+ { key: "\u2191\u2193", label: "select" },
4943
+ { key: "enter", label: "run" },
4944
+ { key: "esc", label: "close" }
4945
+ ]
5022
4946
  }, undefined, false, undefined, this),
5023
4947
  children: content
5024
4948
  }, undefined, false, undefined, this);
@@ -5039,6 +4963,7 @@ var init_CommandPalette = __esm(() => {
5039
4963
  });
5040
4964
 
5041
4965
  // src/ui/modals.tsx
4966
+ import { TextAttributes as TextAttributes6 } from "@opentui/core";
5042
4967
  import { Data as Data3 } from "effect";
5043
4968
  import { jsxDEV as jsxDEV8, Fragment as Fragment6 } from "@opentui/react/jsx-dev-runtime";
5044
4969
  var filterLabels = (labels, query) => {
@@ -5194,7 +5119,12 @@ var filterLabels = (labels, query) => {
5194
5119
  }, undefined, true, undefined, this),
5195
5120
  bodyPadding: 1,
5196
5121
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5197
- items: [{ key: "enter", label: "open" }, { key: "ctrl-u", label: "clear" }, { key: "ctrl-w", label: "word" }, { key: "esc", label: "cancel" }]
5122
+ items: [
5123
+ { key: "enter", label: "open" },
5124
+ { key: "ctrl-u", label: "clear" },
5125
+ { key: "ctrl-w", label: "word" },
5126
+ { key: "esc", label: "cancel" }
5127
+ ]
5198
5128
  }, undefined, false, undefined, this),
5199
5129
  children: state.error ? /* @__PURE__ */ jsxDEV8(PlainLine, {
5200
5130
  text: fitCell(state.error, contentWidth),
@@ -5250,7 +5180,7 @@ var filterLabels = (labels, query) => {
5250
5180
  }, undefined, false, undefined, this),
5251
5181
  /* @__PURE__ */ jsxDEV8("span", {
5252
5182
  fg: colors.muted,
5253
- children: " move "
5183
+ children: " move "
5254
5184
  }, undefined, false, undefined, this),
5255
5185
  /* @__PURE__ */ jsxDEV8("span", {
5256
5186
  fg: colors.count,
@@ -5263,7 +5193,7 @@ var filterLabels = (labels, query) => {
5263
5193
  filtered.length > maxVisible ? /* @__PURE__ */ jsxDEV8("span", {
5264
5194
  fg: colors.muted,
5265
5195
  children: [
5266
- " ",
5196
+ " ",
5267
5197
  selectedIndex + 1,
5268
5198
  "/",
5269
5199
  filtered.length
@@ -5322,7 +5252,7 @@ var filterLabels = (labels, query) => {
5322
5252
  }, undefined, false, undefined, this),
5323
5253
  /* @__PURE__ */ jsxDEV8("span", {
5324
5254
  bg: labelColor(label),
5325
- children: " "
5255
+ children: " "
5326
5256
  }, undefined, false, undefined, this),
5327
5257
  /* @__PURE__ */ jsxDEV8("span", {
5328
5258
  children: [
@@ -5363,7 +5293,11 @@ var filterLabels = (labels, query) => {
5363
5293
  placeholder: "Filter",
5364
5294
  countText,
5365
5295
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5366
- items: [{ key: "\u2191\u2193", label: "move" }, { key: "enter", label: "jump" }, { key: "esc", label: "close" }]
5296
+ items: [
5297
+ { key: "\u2191\u2193", label: "move" },
5298
+ { key: "enter", label: "jump" },
5299
+ { key: "esc", label: "close" }
5300
+ ]
5367
5301
  }, undefined, false, undefined, this),
5368
5302
  children: visibleFiles.length === 0 ? /* @__PURE__ */ jsxDEV8(Fragment6, {
5369
5303
  children: [
@@ -5436,7 +5370,11 @@ var filterLabels = (labels, query) => {
5436
5370
  fg: colors.muted
5437
5371
  }, undefined, false, undefined, this),
5438
5372
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5439
- items: [{ key: "\u2191\u2193", label: "move" }, { key: "enter", label: "confirm" }, { key: "esc", label: "close" }]
5373
+ items: [
5374
+ { key: "\u2191\u2193", label: "move" },
5375
+ { key: "enter", label: "confirm" },
5376
+ { key: "esc", label: "close" }
5377
+ ]
5440
5378
  }, undefined, false, undefined, this),
5441
5379
  children: state.loading ? /* @__PURE__ */ jsxDEV8(Fragment6, {
5442
5380
  children: [
@@ -5521,7 +5459,10 @@ var filterLabels = (labels, query) => {
5521
5459
  }, undefined, false, undefined, this),
5522
5460
  bodyPadding: 1,
5523
5461
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5524
- items: [{ key: "enter", label: "close" }, { key: "esc", label: "cancel" }]
5462
+ items: [
5463
+ { key: "enter", label: "close" },
5464
+ { key: "esc", label: "cancel" }
5465
+ ]
5525
5466
  }, undefined, false, undefined, this),
5526
5467
  children: state.error ? /* @__PURE__ */ jsxDEV8(PlainLine, {
5527
5468
  text: fitCell(state.error, contentWidth),
@@ -5612,7 +5553,11 @@ var filterLabels = (labels, query) => {
5612
5553
  }, undefined, false, undefined, this),
5613
5554
  bodyPadding: 1,
5614
5555
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5615
- items: [{ key: "enter", label: "save" }, { key: "shift-enter", label: "newline" }, { key: "esc", label: "cancel" }]
5556
+ items: [
5557
+ { key: "enter", label: "save" },
5558
+ { key: "shift-enter", label: "newline" },
5559
+ { key: "esc", label: "cancel" }
5560
+ ]
5616
5561
  }, undefined, false, undefined, this),
5617
5562
  children: [
5618
5563
  state.error ? /* @__PURE__ */ jsxDEV8(PlainLine, {
@@ -5627,27 +5572,40 @@ var filterLabels = (labels, query) => {
5627
5572
  modalWidth,
5628
5573
  modalHeight,
5629
5574
  offsetLeft,
5630
- offsetTop,
5631
- loadingIndicator
5575
+ offsetTop
5632
5576
  }) => {
5633
- const { contentWidth, bodyHeight } = standardModalDims(modalWidth, modalHeight);
5577
+ const { innerWidth, contentWidth } = standardModalDims(modalWidth, modalHeight);
5634
5578
  const selectedIndex = Math.max(0, Math.min(state.selectedIndex, submitReviewOptions.length - 1));
5635
- const editorHeight = Math.max(1, bodyHeight - submitReviewOptions.length - (state.error ? 1 : 0));
5579
+ const headerRows = 1;
5580
+ const actionHeight = submitReviewOptions.length;
5581
+ const errorHeight = state.error ? 1 : 0;
5582
+ const footerRows = 1;
5583
+ const dividerRows = 3;
5584
+ const frameBorderRows = 2;
5585
+ const editorHeight = Math.max(1, modalHeight - frameBorderRows - headerRows - actionHeight - errorHeight - footerRows - dividerRows);
5586
+ const actionDividerRow = headerRows;
5587
+ const editorDividerRow = headerRows + 1 + actionHeight;
5588
+ const footerDividerRow = editorDividerRow + 1 + errorHeight + editorHeight;
5636
5589
  const lineRanges = commentEditorLines(state.body);
5637
5590
  const cursor = clampCursor(state.body, state.cursor);
5638
5591
  const cursorLineIndex = cursorLineIndexForLines(lineRanges, cursor);
5639
5592
  const visibleStart = Math.min(Math.max(0, lineRanges.length - editorHeight), Math.max(0, cursorLineIndex - editorHeight + 1));
5640
5593
  const visibleLines = lineRanges.slice(visibleStart, visibleStart + editorHeight);
5641
- const title = state.number ? `Submit review #${state.number}` : "Submit review";
5642
- const rightText = state.running ? `${loadingIndicator} submitting` : submitReviewOptions[selectedIndex]?.title ?? "review";
5643
- const subtitleText = state.repository ? shortRepoName(state.repository) : "Choose a review action and optional summary";
5594
+ const title = "Submit review";
5595
+ const editorFocused = state.focus === "body";
5644
5596
  const renderEditorLine = (line, index) => {
5645
5597
  const lineIndex = visibleStart + index;
5646
5598
  const isCursorLine = lineIndex === cursorLineIndex;
5647
5599
  const cursorColumn = Math.max(0, Math.min(cursor - line.start, line.text.length));
5648
- const viewStart = isCursorLine ? Math.max(0, cursorColumn - contentWidth + 1) : 0;
5600
+ const viewStart = editorFocused && isCursorLine ? Math.max(0, cursorColumn - contentWidth + 1) : 0;
5649
5601
  const visibleText = line.text.slice(viewStart, viewStart + contentWidth);
5650
- if (!isCursorLine) {
5602
+ if (!editorFocused || !isCursorLine) {
5603
+ if (state.body.length === 0 && lineIndex === 0) {
5604
+ return /* @__PURE__ */ jsxDEV8(PlainLine, {
5605
+ text: fitCell("Optional review summary...", contentWidth),
5606
+ fg: colors.muted
5607
+ }, lineIndex, false, undefined, this);
5608
+ }
5651
5609
  return /* @__PURE__ */ jsxDEV8(PlainLine, {
5652
5610
  text: fitCell(visibleText, contentWidth),
5653
5611
  fg: state.body.length > 0 ? colors.text : colors.muted
@@ -5676,52 +5634,89 @@ var filterLabels = (labels, query) => {
5676
5634
  ]
5677
5635
  }, lineIndex, true, undefined, this);
5678
5636
  };
5679
- return /* @__PURE__ */ jsxDEV8(StandardModal, {
5637
+ return /* @__PURE__ */ jsxDEV8(ModalFrame, {
5680
5638
  left: offsetLeft,
5681
5639
  top: offsetTop,
5682
5640
  width: modalWidth,
5683
5641
  height: modalHeight,
5684
- title,
5685
- headerRight: { text: rightText, pending: state.running },
5686
- subtitle: /* @__PURE__ */ jsxDEV8(PlainLine, {
5687
- text: fitCell(subtitleText, contentWidth),
5688
- fg: colors.muted
5689
- }, undefined, false, undefined, this),
5690
- bodyPadding: 1,
5691
- footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5692
- items: [{ key: "tab", label: "action" }, { key: "enter", label: "submit" }, { key: "shift-enter", label: "newline" }, { key: "esc", label: "cancel" }]
5693
- }, undefined, false, undefined, this),
5642
+ junctionRows: [actionDividerRow, editorDividerRow, footerDividerRow],
5694
5643
  children: [
5695
- submitReviewOptions.map((option, index) => {
5696
- const isSelected = index === selectedIndex;
5697
- const titleWidth = Math.min(18, Math.max(8, contentWidth - 8));
5698
- const descriptionWidth = Math.max(1, contentWidth - titleWidth - 4);
5699
- return /* @__PURE__ */ jsxDEV8(TextLine, {
5700
- bg: isSelected ? colors.selectedBg : undefined,
5701
- fg: isSelected ? colors.selectedText : colors.text,
5702
- children: [
5703
- /* @__PURE__ */ jsxDEV8("span", {
5704
- fg: submitReviewEventColor(option.event),
5705
- children: isSelected ? "\u203A" : " "
5706
- }, undefined, false, undefined, this),
5707
- /* @__PURE__ */ jsxDEV8("span", {
5708
- children: [
5709
- " ",
5710
- fitCell(option.title, titleWidth)
5711
- ]
5712
- }, undefined, true, undefined, this),
5713
- /* @__PURE__ */ jsxDEV8("span", {
5714
- fg: isSelected ? colors.selectedText : colors.muted,
5715
- children: fitCell(option.description, descriptionWidth)
5716
- }, undefined, false, undefined, this)
5717
- ]
5718
- }, option.event, true, undefined, this);
5719
- }),
5720
- state.error ? /* @__PURE__ */ jsxDEV8(PlainLine, {
5721
- text: fitCell(state.error, contentWidth),
5722
- fg: colors.error
5644
+ /* @__PURE__ */ jsxDEV8(PaddedRow, {
5645
+ children: /* @__PURE__ */ jsxDEV8(TextLine, {
5646
+ children: /* @__PURE__ */ jsxDEV8("span", {
5647
+ fg: colors.accent,
5648
+ attributes: TextAttributes6.BOLD,
5649
+ children: title
5650
+ }, undefined, false, undefined, this)
5651
+ }, undefined, false, undefined, this)
5652
+ }, undefined, false, undefined, this),
5653
+ /* @__PURE__ */ jsxDEV8(Divider, {
5654
+ width: innerWidth
5655
+ }, undefined, false, undefined, this),
5656
+ /* @__PURE__ */ jsxDEV8("box", {
5657
+ height: actionHeight,
5658
+ flexDirection: "column",
5659
+ paddingLeft: 1,
5660
+ paddingRight: 1,
5661
+ children: submitReviewOptions.map((option, index) => {
5662
+ const isSelected = index === selectedIndex;
5663
+ const isFocusedSelection = isSelected && state.focus === "action";
5664
+ const titleWidth = Math.min(18, Math.max(8, contentWidth - 8));
5665
+ const descriptionWidth = Math.max(1, contentWidth - titleWidth - 4);
5666
+ return /* @__PURE__ */ jsxDEV8(TextLine, {
5667
+ bg: isFocusedSelection ? colors.selectedBg : undefined,
5668
+ fg: isFocusedSelection ? colors.selectedText : colors.text,
5669
+ children: [
5670
+ /* @__PURE__ */ jsxDEV8("span", {
5671
+ fg: submitReviewEventColor(option.event),
5672
+ children: isFocusedSelection ? "\u203A" : isSelected ? "\u2713" : " "
5673
+ }, undefined, false, undefined, this),
5674
+ /* @__PURE__ */ jsxDEV8("span", {
5675
+ children: [
5676
+ " ",
5677
+ fitCell(option.title, titleWidth)
5678
+ ]
5679
+ }, undefined, true, undefined, this),
5680
+ /* @__PURE__ */ jsxDEV8("span", {
5681
+ fg: isFocusedSelection ? colors.selectedText : colors.muted,
5682
+ children: fitCell(option.description, descriptionWidth)
5683
+ }, undefined, false, undefined, this)
5684
+ ]
5685
+ }, option.event, true, undefined, this);
5686
+ })
5687
+ }, undefined, false, undefined, this),
5688
+ /* @__PURE__ */ jsxDEV8(Divider, {
5689
+ width: innerWidth
5690
+ }, undefined, false, undefined, this),
5691
+ state.error ? /* @__PURE__ */ jsxDEV8(PaddedRow, {
5692
+ children: /* @__PURE__ */ jsxDEV8(PlainLine, {
5693
+ text: fitCell(state.error, contentWidth),
5694
+ fg: colors.error
5695
+ }, undefined, false, undefined, this)
5723
5696
  }, undefined, false, undefined, this) : null,
5724
- visibleLines.map(renderEditorLine)
5697
+ /* @__PURE__ */ jsxDEV8("box", {
5698
+ height: editorHeight,
5699
+ flexDirection: "column",
5700
+ paddingLeft: 1,
5701
+ paddingRight: 1,
5702
+ children: visibleLines.map(renderEditorLine)
5703
+ }, undefined, false, undefined, this),
5704
+ /* @__PURE__ */ jsxDEV8(Divider, {
5705
+ width: innerWidth
5706
+ }, undefined, false, undefined, this),
5707
+ /* @__PURE__ */ jsxDEV8(PaddedRow, {
5708
+ children: /* @__PURE__ */ jsxDEV8(HintRow, {
5709
+ items: editorFocused ? [
5710
+ { key: "shift-enter", label: "newline" },
5711
+ { key: "enter", label: "submit" },
5712
+ { key: "esc", label: "actions" }
5713
+ ] : [
5714
+ { key: "\u2191\u2193", label: "action" },
5715
+ { key: "enter", label: "summary" },
5716
+ { key: "esc", label: "cancel" }
5717
+ ]
5718
+ }, undefined, false, undefined, this)
5719
+ }, undefined, false, undefined, this)
5725
5720
  ]
5726
5721
  }, undefined, true, undefined, this);
5727
5722
  }, commentThreadRows = (comments, width) => comments.flatMap((comment) => commentDisplayRows({ item: comment, width })), CommentThreadModal = ({
@@ -5753,7 +5748,11 @@ var filterLabels = (labels, query) => {
5753
5748
  }, undefined, false, undefined, this),
5754
5749
  bodyPadding: 1,
5755
5750
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5756
- items: [{ key: "\u2191\u2193", label: "scroll" }, { key: "enter", label: "comment" }, { key: "esc", label: "close" }]
5751
+ items: [
5752
+ { key: "\u2191\u2193", label: "scroll" },
5753
+ { key: "enter", label: "comment" },
5754
+ { key: "esc", label: "close" }
5755
+ ]
5757
5756
  }, undefined, false, undefined, this),
5758
5757
  children: visibleRows.length === 0 ? /* @__PURE__ */ jsxDEV8(PlainLine, {
5759
5758
  text: fitCell("No comments on this line.", contentWidth),
@@ -5806,7 +5805,12 @@ var filterLabels = (labels, query) => {
5806
5805
  fg: colors.muted
5807
5806
  }, undefined, false, undefined, this),
5808
5807
  footer: /* @__PURE__ */ jsxDEV8(HintRow, {
5809
- items: [{ key: "\u2191\u2193", label: "preview" }, { key: "/", label: "filter" }, { key: "enter", label: "select" }, { key: "esc", label: "cancel" }]
5808
+ items: [
5809
+ { key: "\u2191\u2193", label: "preview" },
5810
+ { key: "/", label: "filter" },
5811
+ { key: "enter", label: "select" },
5812
+ { key: "esc", label: "cancel" }
5813
+ ]
5810
5814
  }, undefined, false, undefined, this),
5811
5815
  children: visibleThemes.length === 0 ? /* @__PURE__ */ jsxDEV8(Fragment6, {
5812
5816
  children: [
@@ -5930,6 +5934,7 @@ var init_modals = __esm(() => {
5930
5934
  initialSubmitReviewModalState = {
5931
5935
  repository: null,
5932
5936
  number: null,
5937
+ focus: "action",
5933
5938
  selectedIndex: 0,
5934
5939
  body: "",
5935
5940
  cursor: 0,
@@ -6032,7 +6037,7 @@ var DiffPaneHeader = ({ pullRequest, paneWidth }) => {
6032
6037
  }, undefined, false, undefined, this),
6033
6038
  statsText ? /* @__PURE__ */ jsxDEV9("span", {
6034
6039
  fg: colors.muted,
6035
- children: " "
6040
+ children: " "
6036
6041
  }, undefined, false, undefined, this) : null,
6037
6042
  /* @__PURE__ */ jsxDEV9(FileStats, {
6038
6043
  stats
@@ -6115,7 +6120,10 @@ var DiffPaneHeader = ({ pullRequest, paneWidth }) => {
6115
6120
  }
6116
6121
  if (readyFiles.length === 0 || stackedFiles.length === 0) {
6117
6122
  return /* @__PURE__ */ jsxDEV9(LoadingPane, {
6118
- content: { title: whitespaceMode === "ignore" ? "No non-whitespace diff" : "No diff", hint: whitespaceMode === "ignore" ? "Use the command palette to show whitespace changes" : "This PR has no patch contents" },
6123
+ content: {
6124
+ title: whitespaceMode === "ignore" ? "No non-whitespace diff" : "No diff",
6125
+ hint: whitespaceMode === "ignore" ? "Use the command palette to show whitespace changes" : "This PR has no patch contents"
6126
+ },
6119
6127
  width: paneWidth,
6120
6128
  height
6121
6129
  }, undefined, false, undefined, this);
@@ -6127,7 +6135,10 @@ var DiffPaneHeader = ({ pullRequest, paneWidth }) => {
6127
6135
  markerLabel: diffCommentLineLabel(selectedCommentAnchor),
6128
6136
  groups: [
6129
6137
  [{ text: commentCountText(selectedCommentThread.length), fg: colors.muted }],
6130
- [{ text: "enter", fg: colors.text }, { text: " thread", fg: colors.muted }]
6138
+ [
6139
+ { text: "enter", fg: colors.text },
6140
+ { text: " thread", fg: colors.muted }
6141
+ ]
6131
6142
  ]
6132
6143
  }) : [];
6133
6144
  const stickyScrollTop = Math.max(0, Math.floor(scrollTop));
@@ -6296,7 +6307,7 @@ var init_PullRequestDiffPane = __esm(() => {
6296
6307
  });
6297
6308
 
6298
6309
  // src/ui/PullRequestList.tsx
6299
- import { TextAttributes as TextAttributes6 } from "@opentui/core";
6310
+ import { TextAttributes as TextAttributes7 } from "@opentui/core";
6300
6311
  import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
6301
6312
  var GROUP_ICON = "\u25C6", getRowLayout = (contentWidth, numberWidth, ageWidth) => {
6302
6313
  const reviewWidth = 1;
@@ -6325,7 +6336,7 @@ var GROUP_ICON = "\u25C6", getRowLayout = (contentWidth, numberWidth, ageWidth)
6325
6336
  }, undefined, true, undefined, this),
6326
6337
  /* @__PURE__ */ jsxDEV10("span", {
6327
6338
  fg: color,
6328
- attributes: TextAttributes6.BOLD,
6339
+ attributes: TextAttributes7.BOLD,
6329
6340
  children: /* @__PURE__ */ jsxDEV10(MatchedCell, {
6330
6341
  text: label,
6331
6342
  width: label.length,
@@ -6548,7 +6559,10 @@ var REVIEW_CYCLE, MERGEABLE_CYCLE, synthCheckSummary = (passed, total) => {
6548
6559
  if (index % 5 === 0)
6549
6560
  return [{ name: "bug", color: "#d73a4a" }];
6550
6561
  if (index % 7 === 0)
6551
- return [{ name: "enhancement", color: "#a2eeef" }, { name: "tests", color: "#0e8a16" }];
6562
+ return [
6563
+ { name: "enhancement", color: "#a2eeef" },
6564
+ { name: "tests", color: "#0e8a16" }
6565
+ ];
6552
6566
  return [];
6553
6567
  }, buildPullRequest = (index, options) => {
6554
6568
  const repoIndex = index % options.repoCount;
@@ -6729,22 +6743,14 @@ var parseOptionalPositiveInt = (value, fallback) => {
6729
6743
  const normalized = query.trim().toLowerCase();
6730
6744
  if (normalized.length === 0)
6731
6745
  return 0;
6732
- const fields = [
6733
- pullRequest.title.toLowerCase(),
6734
- pullRequest.repository.toLowerCase(),
6735
- String(pullRequest.number)
6736
- ];
6746
+ const fields = [pullRequest.title.toLowerCase(), pullRequest.repository.toLowerCase(), String(pullRequest.number)];
6737
6747
  const scores = fields.flatMap((field, index) => {
6738
6748
  const matchIndex = field.indexOf(normalized);
6739
6749
  return matchIndex >= 0 ? [index * 1000 + matchIndex] : [];
6740
6750
  });
6741
6751
  return scores.length > 0 ? Math.min(...scores) : null;
6742
6752
  }, pullRequestMetadataText = (pullRequest) => {
6743
- const lines = [
6744
- pullRequest.title,
6745
- `${pullRequest.repository} #${pullRequest.number}`,
6746
- pullRequest.url
6747
- ];
6753
+ const lines = [pullRequest.title, `${pullRequest.repository} #${pullRequest.number}`, pullRequest.url];
6748
6754
  const review = reviewLabel(pullRequest);
6749
6755
  if (review)
6750
6756
  lines.push(`review: ${review}`);
@@ -6800,13 +6806,7 @@ var parseOptionalPositiveInt = (value, fallback) => {
6800
6806
  for (const target of diffSideTargets(diff, entry.anchor, entry.view)) {
6801
6807
  target.setLineColor(entry.anchor.localRenderLine, color);
6802
6808
  }
6803
- }, getDetailPlaceholderContent = ({
6804
- status,
6805
- retryProgress,
6806
- loadingIndicator,
6807
- visibleCount,
6808
- filterText
6809
- }) => {
6809
+ }, getDetailPlaceholderContent = ({ status, retryProgress, loadingIndicator, visibleCount, filterText }) => {
6810
6810
  if (status === "loading") {
6811
6811
  return {
6812
6812
  title: `${loadingIndicator} Loading pull requests`,
@@ -7457,7 +7457,16 @@ var parseOptionalPositiveInt = (value, fallback) => {
7457
7457
  suppressNextDiffCommentScrollRef.current = false;
7458
7458
  }
7459
7459
  diffCommentLineColorsRef.current = { contextKey: diffLineColorContextKey, entries: nextEntries };
7460
- }, [selectedDiffCommentAnchor?.renderLine, selectedDiffCommentAnchor?.localRenderLine, selectedDiffCommentAnchor?.side, selectedDiffCommentAnchor?.fileIndex, selectedDiffCommentRangeAnchors, diffLineColorContextKey, effectiveDiffRenderView, diffCommentThreadAnchors]);
7460
+ }, [
7461
+ selectedDiffCommentAnchor?.renderLine,
7462
+ selectedDiffCommentAnchor?.localRenderLine,
7463
+ selectedDiffCommentAnchor?.side,
7464
+ selectedDiffCommentAnchor?.fileIndex,
7465
+ selectedDiffCommentRangeAnchors,
7466
+ diffLineColorContextKey,
7467
+ effectiveDiffRenderView,
7468
+ diffCommentThreadAnchors
7469
+ ]);
7461
7470
  useEffect3(() => {
7462
7471
  if (!diffFullView)
7463
7472
  return;
@@ -7490,7 +7499,15 @@ var parseOptionalPositiveInt = (value, fallback) => {
7490
7499
  if (pullRequestStatus !== "ready" || !selectedPullRequest)
7491
7500
  return;
7492
7501
  hydratePullRequestDetails(selectedPullRequest, true);
7493
- }, [pullRequestStatus, selectedPullRequest?.url, selectedPullRequest?.headRefOid, selectedPullRequest?.state, selectedPullRequest?.detailLoaded, selectedPullRequest?.repository, selectedPullRequest?.number]);
7502
+ }, [
7503
+ pullRequestStatus,
7504
+ selectedPullRequest?.url,
7505
+ selectedPullRequest?.headRefOid,
7506
+ selectedPullRequest?.state,
7507
+ selectedPullRequest?.detailLoaded,
7508
+ selectedPullRequest?.repository,
7509
+ selectedPullRequest?.number
7510
+ ]);
7494
7511
  useEffect3(() => {
7495
7512
  if (pullRequestStatus !== "ready" || !selectedPullRequest)
7496
7513
  return;
@@ -7813,13 +7830,15 @@ var parseOptionalPositiveInt = (value, fallback) => {
7813
7830
  return { ...current, body: next.body, cursor: next.cursor, error: null };
7814
7831
  });
7815
7832
  };
7816
- const openSubmitReviewModal = () => {
7833
+ const openSubmitReviewModal = (initialEvent = "APPROVE") => {
7817
7834
  if (!selectedPullRequest || selectedPullRequest.state !== "open")
7818
7835
  return;
7836
+ const selectedIndex2 = Math.max(0, submitReviewOptions.findIndex((option) => option.event === initialEvent));
7819
7837
  setSubmitReviewModal({
7820
7838
  repository: selectedPullRequest.repository,
7821
7839
  number: selectedPullRequest.number,
7822
- selectedIndex: 0,
7840
+ focus: "action",
7841
+ selectedIndex: selectedIndex2,
7823
7842
  body: "",
7824
7843
  cursor: 0,
7825
7844
  running: false,
@@ -8203,8 +8222,11 @@ var parseOptionalPositiveInt = (value, fallback) => {
8203
8222
  return true;
8204
8223
  }
8205
8224
  if (submitReviewModalActive) {
8206
- editSubmitReview((state) => insertText(state, text.replace(/\r\n?/g, `
8207
- `)));
8225
+ setSubmitReviewModal((current) => {
8226
+ const next = insertText({ body: current.body, cursor: current.cursor }, text.replace(/\r\n?/g, `
8227
+ `));
8228
+ return { ...current, focus: "body", body: next.body, cursor: next.cursor, error: null };
8229
+ });
8208
8230
  return true;
8209
8231
  }
8210
8232
  if (labelModalActive) {
@@ -8231,7 +8253,18 @@ var parseOptionalPositiveInt = (value, fallback) => {
8231
8253
  return () => {
8232
8254
  keyInput.off("paste", handlePaste);
8233
8255
  };
8234
- }, [renderer, commandPaletteActive, openRepositoryModalActive, themeModalActive, themeModal.filterMode, commentModalActive, submitReviewModalActive, labelModalActive, changedFilesModalActive, filterMode]);
8256
+ }, [
8257
+ renderer,
8258
+ commandPaletteActive,
8259
+ openRepositoryModalActive,
8260
+ themeModalActive,
8261
+ themeModal.filterMode,
8262
+ commentModalActive,
8263
+ submitReviewModalActive,
8264
+ labelModalActive,
8265
+ changedFilesModalActive,
8266
+ filterMode
8267
+ ]);
8235
8268
  const appCommands = buildAppCommands({
8236
8269
  pullRequestStatus,
8237
8270
  filterQuery,
@@ -8335,19 +8368,18 @@ var parseOptionalPositiveInt = (value, fallback) => {
8335
8368
  const repository = parseRepositoryInput(commandPalette.query);
8336
8369
  if (!repository || repository === selectedRepository)
8337
8370
  return [];
8338
- return [defineCommand({
8339
- id: `view.repository.dynamic:${repository}`,
8340
- title: `Open ${repository}`,
8341
- scope: "View",
8342
- subtitle: "Switch to this repository",
8343
- run: () => switchViewTo({ _tag: "Repository", repository })
8344
- })];
8371
+ return [
8372
+ defineCommand({
8373
+ id: `view.repository.dynamic:${repository}`,
8374
+ title: `Open ${repository}`,
8375
+ scope: "View",
8376
+ subtitle: "Switch to this repository",
8377
+ run: () => switchViewTo({ _tag: "Repository", repository })
8378
+ })
8379
+ ];
8345
8380
  })();
8346
8381
  const staticPaletteCommands = commandPaletteActive ? filterCommands(appCommands.filter((command2) => command2.id !== "command.open" && commandEnabled(command2)), commandPalette.query) : [];
8347
- const commandPaletteCommands = commandPaletteActive ? [
8348
- ...dynamicPaletteCommands,
8349
- ...commandPalette.query.trim().length > 0 ? staticPaletteCommands : sortCommandsByScope(staticPaletteCommands)
8350
- ] : [];
8382
+ const commandPaletteCommands = commandPaletteActive ? [...dynamicPaletteCommands, ...commandPalette.query.trim().length > 0 ? staticPaletteCommands : sortCommandsByScope(staticPaletteCommands)] : [];
8351
8383
  const selectedCommandIndex = clampCommandIndex(commandPalette.selectedIndex, commandPaletteCommands);
8352
8384
  const selectedCommand = commandPaletteCommands[selectedCommandIndex] ?? null;
8353
8385
  const moveMergeSelection = (delta) => setMergeModal((current) => {
@@ -8485,8 +8517,15 @@ var parseOptionalPositiveInt = (value, fallback) => {
8485
8517
  moveSelection: moveChangedFileSelection
8486
8518
  },
8487
8519
  submitReviewModal: {
8488
- closeModal: closeActiveModal,
8520
+ summaryFocused: submitReviewModal.focus === "body",
8521
+ handleEscape: () => {
8522
+ if (submitReviewModal.focus === "body")
8523
+ setSubmitReviewModal((current) => ({ ...current, focus: "action" }));
8524
+ else
8525
+ closeActiveModal();
8526
+ },
8489
8527
  submit: confirmSubmitReview,
8528
+ focusSummary: () => setSubmitReviewModal((current) => ({ ...current, focus: "body", error: null })),
8490
8529
  insertNewline: () => editSubmitReview((state) => insertText(state, `
8491
8530
  `)),
8492
8531
  moveActionSelection: moveSubmitReviewActionSelection,
@@ -8581,7 +8620,7 @@ var parseOptionalPositiveInt = (value, fallback) => {
8581
8620
  alignAnchor: alignSelectedDiffCommentAnchor,
8582
8621
  selectSide: selectDiffCommentSide,
8583
8622
  openChangedFiles: () => runCommandById("diff.changed-files"),
8584
- openSubmitReview: () => runCommandById("diff.submit-review"),
8623
+ openSubmitReview: () => runCommandById("pull.submit-review"),
8585
8624
  nextFile: () => runCommandById("diff.next-file"),
8586
8625
  previousFile: () => runCommandById("diff.previous-file"),
8587
8626
  openInBrowser: () => runCommandById("pull.open-browser")
@@ -8597,6 +8636,7 @@ var parseOptionalPositiveInt = (value, fallback) => {
8597
8636
  openLabels: () => runCommandById("pull.labels"),
8598
8637
  openMerge: () => runCommandById("pull.merge"),
8599
8638
  toggleDraft: () => runCommandById("pull.toggle-draft"),
8639
+ openReview: () => runCommandById("pull.submit-review"),
8600
8640
  refresh: () => runCommandById("pull.refresh"),
8601
8641
  openInBrowser: () => runCommandById("pull.open-browser"),
8602
8642
  copyMetadata: () => runCommandById("pull.copy-metadata")
@@ -8663,6 +8703,8 @@ var parseOptionalPositiveInt = (value, fallback) => {
8663
8703
  return;
8664
8704
  }
8665
8705
  if (submitReviewModalActive) {
8706
+ if (submitReviewModal.focus !== "body")
8707
+ return;
8666
8708
  const text = printableKeyText(key);
8667
8709
  if (text)
8668
8710
  editSubmitReview((state) => insertText(state, text));
@@ -9066,7 +9108,6 @@ var parseOptionalPositiveInt = (value, fallback) => {
9066
9108
  diffFullView,
9067
9109
  diffRangeActive: diffCommentRangeActive,
9068
9110
  hasSelection: selectedPullRequest !== null,
9069
- canCloseSelection: selectedPullRequest?.state === "open",
9070
9111
  hasError: pullRequestStatus === "error",
9071
9112
  isLoading: pullRequestStatus === "loading" || isRefreshingPullRequests || isHydratingPullRequestDetails || closeModal.running || mergeModal.running || submitReviewModal.running,
9072
9113
  loadingIndicator,
@@ -9121,8 +9162,7 @@ var parseOptionalPositiveInt = (value, fallback) => {
9121
9162
  modalWidth: submitReviewModalWidth,
9122
9163
  modalHeight: submitReviewModalHeight,
9123
9164
  offsetLeft: submitReviewModalLeft,
9124
- offsetTop: submitReviewModalTop,
9125
- loadingIndicator
9165
+ offsetTop: submitReviewModalTop
9126
9166
  }, undefined, false, undefined, this) : null,
9127
9167
  mergeModalActive ? /* @__PURE__ */ jsxDEV11(MergeModal, {
9128
9168
  state: mergeModal,
@@ -9191,12 +9231,12 @@ var init_App = __esm(async () => {
9191
9231
  init_spinner();
9192
9232
  mockPrCount = parseOptionalPositiveInt(process.env.GHUI_MOCK_PR_COUNT, null);
9193
9233
  pullRequestPageSize = Math.min(100, parseOptionalPositiveInt(process.env.GHUI_PR_PAGE_SIZE, config.prPageSize) ?? config.prPageSize);
9194
- githubServiceLayer = mockPrCount !== null ? (await Promise.resolve().then(() => (init_MockGitHubService(), exports_MockGitHubService))).MockGitHubService.layer({ prCount: mockPrCount, repoCount: parseOptionalPositiveInt(process.env.GHUI_MOCK_REPO_COUNT, 4) ?? 4 }) : GitHubService.layerNoDeps;
9234
+ githubServiceLayer = mockPrCount !== null ? (await Promise.resolve().then(() => (init_MockGitHubService(), exports_MockGitHubService))).MockGitHubService.layer({
9235
+ prCount: mockPrCount,
9236
+ repoCount: parseOptionalPositiveInt(process.env.GHUI_MOCK_REPO_COUNT, 4) ?? 4
9237
+ }) : GitHubService.layerNoDeps;
9195
9238
  githubRuntime = Atom.runtime(Layer7.mergeAll(githubServiceLayer, Clipboard.layerNoDeps, BrowserOpener.layerNoDeps).pipe(Layer7.provide(CommandRunner.layer), Layer7.provideMerge(Observability.layer)));
9196
- [initialThemeId, initialDiffWhitespaceMode] = await Promise.all([
9197
- Effect9.runPromise(loadStoredThemeId),
9198
- Effect9.runPromise(loadStoredDiffWhitespaceMode)
9199
- ]);
9239
+ [initialThemeId, initialDiffWhitespaceMode] = await Promise.all([Effect9.runPromise(loadStoredThemeId), Effect9.runPromise(loadStoredDiffWhitespaceMode)]);
9200
9240
  retryProgressAtom = Atom.make(initialRetryProgress).pipe(Atom.keepAlive);
9201
9241
  activeViewAtom = Atom.make(initialPullRequestView()).pipe(Atom.keepAlive);
9202
9242
  queueLoadCacheAtom = Atom.make({}).pipe(Atom.keepAlive);
@@ -9291,10 +9331,7 @@ var init_App = __esm(async () => {
9291
9331
  seenUrls.add(pullRequest.url);
9292
9332
  return recentlyCompleted[pullRequest.url] ?? overrides[pullRequest.url] ?? pullRequest;
9293
9333
  });
9294
- return [
9295
- ...open,
9296
- ...Object.values(recentlyCompleted).filter((pullRequest) => !seenUrls.has(pullRequest.url))
9297
- ];
9334
+ return [...open, ...Object.values(recentlyCompleted).filter((pullRequest) => !seenUrls.has(pullRequest.url))];
9298
9335
  });
9299
9336
  effectiveFilterQueryAtom = Atom.make((get2) => (get2(filterModeAtom) ? get2(filterDraftAtom) : get2(filterQueryAtom)).trim().toLowerCase());
9300
9337
  filteredPullRequestsAtom = Atom.make((get2) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitlangton/ghui",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Terminal UI for GitHub pull requests",
5
5
  "type": "module",
6
6
  "license": "MIT",