gh-manager-cli 1.40.0 → 1.40.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.40.2](https://github.com/wiiiimm/gh-manager-cli/compare/v1.40.1...v1.40.2) (2026-06-05)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * stars toggle footer hint truncation and contextual labels (SWR-359) ([#52](https://github.com/wiiiimm/gh-manager-cli/issues/52)) ([f19ca6f](https://github.com/wiiiimm/gh-manager-cli/commit/f19ca6f4ba81b71133ddc7e5e98df67191d348b0))
7
+
8
+ ## [1.40.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.40.0...v1.40.1) (2026-06-05)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * fill compact mode view with actual per-row heights [semantic pr title] ([#47](https://github.com/wiiiimm/gh-manager-cli/issues/47)) ([23de03f](https://github.com/wiiiimm/gh-manager-cli/commit/23de03f3df240bcebc3ac764a1bf76ab8b553c68))
14
+
1
15
  # [1.40.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.39.1...v1.40.0) (2026-06-05)
2
16
 
3
17
 
package/README.md CHANGED
@@ -273,7 +273,8 @@ Launch the app, then use the keys below:
273
273
  - **Fork Status**: Always enabled - shows commits behind upstream for all forks
274
274
  - **Visibility Filter**: `V` opens modal (All, Public, Private/Internal for enterprise)
275
275
  - **Archive Filter**: `A` toggles archive filter (All → Unarchived → Archived)
276
- - **Stars Mode**: `Shift+S` (personal account only) to view starred repositories
276
+ - **Stars Mode**: `Shift+S` (personal account only) to toggle between your own repos and your starred repos
277
+ - Footer hint shows `Shift+S Starred` in normal mode and `Shift+S My Repos` in starred mode
277
278
 
278
279
  ### Navigation & Account
279
280
  - **Open in browser**: Enter or `O`
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ var require_package = __commonJS({
34
34
  "package.json"(exports, module) {
35
35
  module.exports = {
36
36
  name: "gh-manager-cli",
37
- version: "1.40.0",
37
+ version: "1.40.2",
38
38
  private: false,
39
39
  description: "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
40
40
  license: "MIT",
@@ -115,6 +115,7 @@ var require_package = __commonJS({
115
115
  "semantic-release": "^24.2.7",
116
116
  tsup: "^8.5.0",
117
117
  typescript: "^5.9.2",
118
+ vite: "^6.4.3",
118
119
  vitest: "^4.1.0"
119
120
  },
120
121
  repository: {
@@ -734,6 +735,55 @@ function formatDate(dateStr) {
734
735
  if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
735
736
  return `${Math.floor(diffDays / 365)} years ago`;
736
737
  }
738
+ function computeWindow(items, cursor, listHeight, spacingLines, buffer = 2) {
739
+ const total = items.length;
740
+ if (total === 0) return { start: 0, end: 0 };
741
+ cursor = Math.max(0, Math.min(cursor, total - 1));
742
+ if (spacingLines > 0) {
743
+ const LINES_PER_REPO = 3 + spacingLines;
744
+ const visibleRepos = Math.max(1, Math.floor(listHeight / LINES_PER_REPO));
745
+ if (visibleRepos >= total) return { start: 0, end: total };
746
+ const half = Math.floor(visibleRepos / 2);
747
+ let start2 = Math.max(0, cursor - half - buffer);
748
+ start2 = Math.min(start2, Math.max(0, total - visibleRepos));
749
+ const end2 = Math.min(total, start2 + visibleRepos + buffer);
750
+ return { start: start2, end: end2 };
751
+ }
752
+ const rowHeight = (idx) => items[idx].description ? 3 : 2;
753
+ if (total * 3 <= listHeight) return { start: 0, end: total };
754
+ if (total * 2 <= listHeight) {
755
+ let totalLines = 0;
756
+ for (let i = 0; i < total; i++) totalLines += rowHeight(i);
757
+ if (totalLines <= listHeight) return { start: 0, end: total };
758
+ }
759
+ const halfHeight = Math.floor(listHeight / 2);
760
+ let start = cursor;
761
+ let accBack = 0;
762
+ while (start > 0) {
763
+ const h = rowHeight(start - 1);
764
+ if (accBack + h > halfHeight) break;
765
+ accBack += h;
766
+ start--;
767
+ }
768
+ let end = start;
769
+ let accFwd = 0;
770
+ while (end < total) {
771
+ const h = rowHeight(end);
772
+ if (accFwd + h > listHeight) break;
773
+ accFwd += h;
774
+ end++;
775
+ }
776
+ if (end >= total) {
777
+ let accFill = accFwd;
778
+ while (start > 0) {
779
+ const h = rowHeight(start - 1);
780
+ if (accFill + h > listHeight) break;
781
+ accFill += h;
782
+ start--;
783
+ }
784
+ }
785
+ return { start: Math.max(0, start - buffer), end: Math.min(total, end + buffer) };
786
+ }
737
787
  async function copyToClipboard(text) {
738
788
  try {
739
789
  const clipboardy = await import("clipboardy");
@@ -3240,26 +3290,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
3240
3290
  }
3241
3291
  }, [searchActive, searchItems.length, visibleItems.length, filter]);
3242
3292
  useEffect12(() => {
3243
- setCursor((c) => Math.min(c, Math.max(0, (searchActive ? searchItems.length : items.length) - 1)));
3244
- }, [searchActive, searchItems.length, items.length]);
3293
+ setCursor((c) => Math.min(c, Math.max(0, visibleItems.length - 1)));
3294
+ }, [searchActive, searchItems.length, items.length, visibleItems.length]);
3245
3295
  const headerHeight = 2;
3246
3296
  const footerHeight = 4;
3247
3297
  const containerPadding = 2;
3248
3298
  const contentHeight = Math.max(1, availableHeight - headerHeight - footerHeight - containerPadding);
3249
3299
  const listHeight = Math.max(1, contentHeight - (filterMode ? 2 : 0) - 2);
3250
3300
  const spacingLines = density;
3251
- const windowed = useMemo(() => {
3252
- const total = visibleItems.length;
3253
- const LINES_PER_REPO = 3 + spacingLines;
3254
- const visibleRepos = Math.max(1, Math.floor(listHeight / LINES_PER_REPO));
3255
- if (visibleRepos >= total) return { start: 0, end: total };
3256
- const buffer = 2;
3257
- const half = Math.floor(visibleRepos / 2);
3258
- let start = Math.max(0, cursor - half - buffer);
3259
- start = Math.min(start, Math.max(0, total - visibleRepos));
3260
- const end = Math.min(total, start + visibleRepos + buffer);
3261
- return { start, end };
3262
- }, [visibleItems.length, cursor, listHeight, spacingLines]);
3301
+ const windowed = useMemo(
3302
+ () => computeWindow(visibleItems, cursor, listHeight, spacingLines),
3303
+ [visibleItems, cursor, listHeight, spacingLines]
3304
+ );
3263
3305
  useEffect12(() => {
3264
3306
  const prefetchThreshold = Math.floor(visibleItems.length * 0.8);
3265
3307
  const nearEnd = visibleItems.length > 0 && cursor >= prefetchThreshold;
@@ -3852,10 +3894,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
3852
3894
  /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx20(Text20, { color: "gray", dimColor: modalOpen ? true : void 0, children: "\u2191\u2193 Navigate \u2022 Ctrl+G Top \u2022 G Bottom \u2022 \u23CE/O Open \u2022 R Refresh" }) }),
3853
3895
  /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsxs19(Text20, { color: "gray", dimColor: modalOpen ? true : void 0, children: [
3854
3896
  "/ Search \u2022 S Sort \u2022 D Direction \u2022 T Density \u2022 A Archive Filter",
3855
- !starsMode && " \u2022 V Visibility Filter",
3856
- ownerContext === "personal" && " \u2022 Shift+S Stars"
3897
+ !starsMode && " \u2022 V Visibility Filter"
3857
3898
  ] }) }),
3858
- /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx20(Text20, { color: "gray", dimColor: modalOpen ? true : void 0, children: starsMode ? "I Info \u2022 C Copy URL \u2022 U Unstar Repository" : "I Info \u2022 C Copy URL \u2022 Ctrl+S Un/Star \u2022 Ctrl+R Rename \u2022 Ctrl+A Un/Archive \u2022 Ctrl+V Change Visibility \u2022 Ctrl+F Sync Fork" }) }),
3899
+ /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx20(Text20, { color: "gray", dimColor: modalOpen ? true : void 0, children: starsMode ? "Shift+S My Repos \u2022 I Info \u2022 C Copy URL \u2022 U Unstar Repository" : `${ownerContext === "personal" ? "Shift+S Starred \u2022 " : ""}I Info \u2022 C Copy URL \u2022 Ctrl+S Un/Star \u2022 Ctrl+R Rename \u2022 Ctrl+A Un/Archive \u2022 Ctrl+V Change Visibility \u2022 Ctrl+F Sync Fork` }) }),
3859
3900
  /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx20(Text20, { color: "gray", dimColor: modalOpen ? true : void 0, children: "K Cache Info \u2022 W Org Switch \u2022 Del/Backspace Delete \u2022 Ctrl+L Logout \u2022 Q Quit" }) }),
3860
3901
  /* @__PURE__ */ jsx20(Box19, { width: terminalWidth, justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx20(Text20, { color: "yellow", dimColor: modalOpen ? true : void 0, children: "\u{1F496} Sponsor on GitHub: github.com/sponsors/wiiiimm" }) })
3861
3902
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gh-manager-cli",
3
- "version": "1.40.0",
3
+ "version": "1.40.2",
4
4
  "private": false,
5
5
  "description": "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
6
6
  "license": "MIT",
@@ -81,6 +81,7 @@
81
81
  "semantic-release": "^24.2.7",
82
82
  "tsup": "^8.5.0",
83
83
  "typescript": "^5.9.2",
84
+ "vite": "^6.4.3",
84
85
  "vitest": "^4.1.0"
85
86
  },
86
87
  "repository": {