gh-manager-cli 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +20 -7
- package/dist/index.js +334 -294
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.8.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.8.0...v1.8.1) (2025-09-01)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* prevent duplicate npm publishing when version hasn't changed ([ff0b37b](https://github.com/wiiiimm/gh-manager-cli/commit/ff0b37b99c4232fa2d179a9becf6e314cc218d55))
|
|
7
|
+
|
|
1
8
|
# [1.8.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.7.0...v1.8.0) (2025-08-31)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -142,6 +142,7 @@ Launch the app, then use the keys below:
|
|
|
142
142
|
- Esc: Clear search and return to full repository list
|
|
143
143
|
- Sorting: `S` to cycle field (updated → pushed → name → stars → forks), `D` to toggle direction
|
|
144
144
|
- Display density: `T` to toggle compact/cozy/comfy
|
|
145
|
+
- Workspace switcher: `W` to switch between personal account and organizations
|
|
145
146
|
- Repository info: `I` to view detailed metadata (size, language, timestamps)
|
|
146
147
|
- Open in browser: Enter or `O`
|
|
147
148
|
- Delete repository: `Del` or `Ctrl+Backspace` (with confirmation modal)
|
|
@@ -168,7 +169,7 @@ Status bar shows loaded count vs total. A rate-limit line displays `remaining/li
|
|
|
168
169
|
|
|
169
170
|
Stack:
|
|
170
171
|
- UI: `ink`, `ink-text-input`, `ink-spinner`
|
|
171
|
-
- API: `@octokit/graphql
|
|
172
|
+
- API: `@octokit/graphql`, Apollo Client
|
|
172
173
|
- Config paths: `env-paths`
|
|
173
174
|
- Language: TypeScript
|
|
174
175
|
- Build: `tsup` (CJS output with shebang)
|
|
@@ -188,10 +189,17 @@ Notes:
|
|
|
188
189
|
Project layout:
|
|
189
190
|
- `src/index.tsx` — CLI entry and error handling
|
|
190
191
|
- `src/ui/App.tsx` — token bootstrap, renders `RepoList`
|
|
191
|
-
- `src/ui/RepoList.tsx` — list UI
|
|
192
|
+
- `src/ui/RepoList.tsx` — main list UI with modal management
|
|
193
|
+
- `src/ui/components/` — modular components (modals, repo, common)
|
|
194
|
+
- `modals/` — DeleteModal, ArchiveModal, SyncModal, InfoModal, LogoutModal
|
|
195
|
+
- `repo/` — RepoRow, FilterInput, RepoListHeader
|
|
196
|
+
- `common/` — SlowSpinner and shared UI elements
|
|
197
|
+
- `src/ui/OrgSwitcher.tsx` — organization switching component
|
|
192
198
|
- `src/github.ts` — GraphQL client and queries (repos + rateLimit)
|
|
193
|
-
- `src/config.ts` — token read/write and
|
|
199
|
+
- `src/config.ts` — token read/write and UI preferences
|
|
194
200
|
- `src/types.ts` — shared types
|
|
201
|
+
- `src/utils.ts` — utility functions (truncate, formatDate)
|
|
202
|
+
- `src/apolloMeta.ts` — Apollo cache management
|
|
195
203
|
|
|
196
204
|
## Apollo Cache (Performance)
|
|
197
205
|
|
|
@@ -253,12 +261,17 @@ GH_MANAGER_DEBUG=1 npx gh-manager
|
|
|
253
261
|
|
|
254
262
|
For the up-to-date task board, see [TODOs.md](./TODOs.md).
|
|
255
263
|
|
|
264
|
+
Recently implemented:
|
|
265
|
+
- ✅ Density toggle for row spacing (compact/cozy/comfy)
|
|
266
|
+
- ✅ Repo actions (archive/unarchive, delete) with confirmations
|
|
267
|
+
- ✅ Organization support and switching (press `W`)
|
|
268
|
+
- ✅ Enhanced server-side search with improved UX
|
|
269
|
+
- ✅ Smart infinite scroll with 80% prefetch trigger
|
|
270
|
+
|
|
256
271
|
Highlights on deck:
|
|
257
|
-
- Density toggle for row spacing (compact/cozy/comfy)
|
|
258
|
-
- Repo actions (archive/unarchive, delete) with confirmations
|
|
259
|
-
- Organization support and switching
|
|
260
|
-
- Enhanced server-side search with improved UX
|
|
261
272
|
- Optional OS keychain storage via `keytar`
|
|
273
|
+
- Bulk selection and actions
|
|
274
|
+
- Repository renaming
|
|
262
275
|
|
|
263
276
|
## License
|
|
264
277
|
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var require_package = __commonJS({
|
|
|
19
19
|
"package.json"(exports, module) {
|
|
20
20
|
module.exports = {
|
|
21
21
|
name: "gh-manager-cli",
|
|
22
|
-
version: "1.8.
|
|
22
|
+
version: "1.8.1",
|
|
23
23
|
private: false,
|
|
24
24
|
description: "Interactive CLI to manage your GitHub repos (personal) with Ink",
|
|
25
25
|
license: "MIT",
|
|
@@ -135,13 +135,13 @@ var require_package = __commonJS({
|
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
// src/index.tsx
|
|
138
|
-
import { render, Box as
|
|
138
|
+
import { render, Box as Box7, Text as Text8 } from "ink";
|
|
139
139
|
import "dotenv/config";
|
|
140
140
|
|
|
141
141
|
// src/ui/App.tsx
|
|
142
|
-
import { useEffect as
|
|
143
|
-
import { Box as
|
|
144
|
-
import
|
|
142
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
|
|
143
|
+
import { Box as Box6, Text as Text7, useApp as useApp2, useStdout as useStdout2, useInput as useInput3 } from "ink";
|
|
144
|
+
import TextInput3 from "ink-text-input";
|
|
145
145
|
|
|
146
146
|
// src/config.ts
|
|
147
147
|
import fs from "fs";
|
|
@@ -197,10 +197,10 @@ function storeUIPrefs(patch) {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
// src/ui/RepoList.tsx
|
|
200
|
-
import
|
|
201
|
-
import { Box as
|
|
202
|
-
import
|
|
203
|
-
import
|
|
200
|
+
import React3, { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
|
|
201
|
+
import { Box as Box5, Text as Text6, useApp, useInput as useInput2, useStdout } from "ink";
|
|
202
|
+
import TextInput2 from "ink-text-input";
|
|
203
|
+
import chalk3 from "chalk";
|
|
204
204
|
|
|
205
205
|
// src/apolloMeta.ts
|
|
206
206
|
import fs2 from "fs";
|
|
@@ -329,20 +329,11 @@ function OrgSwitcher({ token, currentContext, onSelect, onClose }) {
|
|
|
329
329
|
] });
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
// src/ui/
|
|
333
|
-
import {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const [frame, setFrame] = useState2(0);
|
|
338
|
-
useEffect2(() => {
|
|
339
|
-
const timer = setInterval(() => {
|
|
340
|
-
setFrame((f) => (f + 1) % frames.length);
|
|
341
|
-
}, 500);
|
|
342
|
-
return () => clearInterval(timer);
|
|
343
|
-
}, [frames.length]);
|
|
344
|
-
return /* @__PURE__ */ jsx2(Text2, { children: frames[frame] });
|
|
345
|
-
}
|
|
332
|
+
// src/ui/components/repo/RepoRow.tsx
|
|
333
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
334
|
+
import chalk2 from "chalk";
|
|
335
|
+
|
|
336
|
+
// src/utils.ts
|
|
346
337
|
function truncate(str, max = 80) {
|
|
347
338
|
if (str.length <= max) return str;
|
|
348
339
|
return str.slice(0, Math.max(0, max - 1)) + "\u2026";
|
|
@@ -359,7 +350,18 @@ function formatDate(dateStr) {
|
|
|
359
350
|
if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
|
|
360
351
|
return `${Math.floor(diffDays / 365)} years ago`;
|
|
361
352
|
}
|
|
362
|
-
|
|
353
|
+
|
|
354
|
+
// src/ui/components/repo/RepoRow.tsx
|
|
355
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
356
|
+
function RepoRow({
|
|
357
|
+
repo,
|
|
358
|
+
selected,
|
|
359
|
+
index,
|
|
360
|
+
maxWidth,
|
|
361
|
+
spacingLines,
|
|
362
|
+
dim,
|
|
363
|
+
forkTracking
|
|
364
|
+
}) {
|
|
363
365
|
const langName = repo.primaryLanguage?.name || "";
|
|
364
366
|
const langColor = repo.primaryLanguage?.color || "#666666";
|
|
365
367
|
const hasCommitData = repo.isFork && repo.parent && repo.defaultBranchRef && repo.parent.defaultBranchRef && repo.parent.defaultBranchRef.target?.history && repo.defaultBranchRef.target?.history;
|
|
@@ -394,65 +396,96 @@ function RepoRow({ repo, selected, index, maxWidth, spacingLines, dim, forkTrack
|
|
|
394
396
|
spacingLines > 0 && /* @__PURE__ */ jsx2(Box2, { height: spacingLines, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) })
|
|
395
397
|
] });
|
|
396
398
|
}
|
|
399
|
+
|
|
400
|
+
// src/ui/components/repo/FilterInput.tsx
|
|
401
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
402
|
+
import TextInput from "ink-text-input";
|
|
403
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
404
|
+
|
|
405
|
+
// src/ui/components/repo/RepoListHeader.tsx
|
|
406
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
407
|
+
|
|
408
|
+
// src/ui/components/common/SlowSpinner.tsx
|
|
409
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
410
|
+
import { Text as Text4 } from "ink";
|
|
411
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
412
|
+
function SlowSpinner() {
|
|
413
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
414
|
+
const [frame, setFrame] = useState2(0);
|
|
415
|
+
useEffect2(() => {
|
|
416
|
+
const timer = setInterval(() => {
|
|
417
|
+
setFrame((f) => (f + 1) % frames.length);
|
|
418
|
+
}, 500);
|
|
419
|
+
return () => clearInterval(timer);
|
|
420
|
+
}, [frames.length]);
|
|
421
|
+
return /* @__PURE__ */ jsx4(Text4, { children: frames[frame] });
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// src/ui/components/repo/RepoListHeader.tsx
|
|
425
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
426
|
+
|
|
427
|
+
// src/ui/RepoList.tsx
|
|
428
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
429
|
+
var PAGE_SIZE = process.env.GH_MANAGER_DEV === "1" || process.env.NODE_ENV === "development" ? 5 : 15;
|
|
397
430
|
function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextChange }) {
|
|
398
431
|
const { exit } = useApp();
|
|
399
432
|
const { stdout } = useStdout();
|
|
400
433
|
const client = useMemo(() => makeClient(token), [token]);
|
|
401
|
-
const [debugMessages, setDebugMessages] =
|
|
434
|
+
const [debugMessages, setDebugMessages] = useState3([]);
|
|
402
435
|
const addDebugMessage = (msg) => {
|
|
403
436
|
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
404
437
|
setDebugMessages((prev) => [...prev.slice(-9), msg]);
|
|
405
438
|
}
|
|
406
439
|
};
|
|
407
|
-
|
|
440
|
+
React3.useEffect(() => {
|
|
408
441
|
addDebugMessage(`[RepoList] Component mounted`);
|
|
409
442
|
}, []);
|
|
410
443
|
const terminalWidth = stdout?.columns ?? 80;
|
|
411
444
|
const availableHeight = maxVisibleRows ?? 20;
|
|
412
|
-
const [items, setItems] =
|
|
413
|
-
const [cursor, setCursor] =
|
|
414
|
-
const [endCursor, setEndCursor] =
|
|
415
|
-
const [hasNextPage, setHasNextPage] =
|
|
416
|
-
const [totalCount, setTotalCount] =
|
|
417
|
-
const [loading, setLoading] =
|
|
418
|
-
const [sortingLoading, setSortingLoading] =
|
|
419
|
-
const [refreshing, setRefreshing] =
|
|
420
|
-
const [loadingMore, setLoadingMore] =
|
|
421
|
-
const [error, setError] =
|
|
422
|
-
const [rateLimit, setRateLimit] =
|
|
423
|
-
const [prevRateLimit, setPrevRateLimit] =
|
|
424
|
-
const [density, setDensity] =
|
|
425
|
-
const [prefsLoaded, setPrefsLoaded] =
|
|
426
|
-
const [ownerContext, setOwnerContext] =
|
|
427
|
-
const [ownerAffiliations, setOwnerAffiliations] =
|
|
428
|
-
const [orgSwitcherOpen, setOrgSwitcherOpen] =
|
|
429
|
-
const [searchItems, setSearchItems] =
|
|
430
|
-
const [searchEndCursor, setSearchEndCursor] =
|
|
431
|
-
const [searchHasNextPage, setSearchHasNextPage] =
|
|
432
|
-
const [searchTotalCount, setSearchTotalCount] =
|
|
433
|
-
const [searchLoading, setSearchLoading] =
|
|
434
|
-
const [deleteMode, setDeleteMode] =
|
|
435
|
-
const [deleteTarget, setDeleteTarget] =
|
|
436
|
-
const [deleteCode, setDeleteCode] =
|
|
437
|
-
const [typedCode, setTypedCode] =
|
|
438
|
-
const [deleting, setDeleting] =
|
|
439
|
-
const [deleteError, setDeleteError] =
|
|
440
|
-
const [deleteConfirmStage, setDeleteConfirmStage] =
|
|
441
|
-
const [confirmFocus, setConfirmFocus] =
|
|
442
|
-
const [archiveMode, setArchiveMode] =
|
|
443
|
-
const [archiveTarget, setArchiveTarget] =
|
|
444
|
-
const [archiving, setArchiving] =
|
|
445
|
-
const [archiveError, setArchiveError] =
|
|
446
|
-
const [archiveFocus, setArchiveFocus] =
|
|
447
|
-
const [syncMode, setSyncMode] =
|
|
448
|
-
const [syncTarget, setSyncTarget] =
|
|
449
|
-
const [syncing, setSyncing] =
|
|
450
|
-
const [syncError, setSyncError] =
|
|
451
|
-
const [syncFocus, setSyncFocus] =
|
|
452
|
-
const [infoMode, setInfoMode] =
|
|
453
|
-
const [logoutMode, setLogoutMode] =
|
|
454
|
-
const [logoutFocus, setLogoutFocus] =
|
|
455
|
-
const [logoutError, setLogoutError] =
|
|
445
|
+
const [items, setItems] = useState3([]);
|
|
446
|
+
const [cursor, setCursor] = useState3(0);
|
|
447
|
+
const [endCursor, setEndCursor] = useState3(null);
|
|
448
|
+
const [hasNextPage, setHasNextPage] = useState3(false);
|
|
449
|
+
const [totalCount, setTotalCount] = useState3(0);
|
|
450
|
+
const [loading, setLoading] = useState3(true);
|
|
451
|
+
const [sortingLoading, setSortingLoading] = useState3(false);
|
|
452
|
+
const [refreshing, setRefreshing] = useState3(false);
|
|
453
|
+
const [loadingMore, setLoadingMore] = useState3(false);
|
|
454
|
+
const [error, setError] = useState3(null);
|
|
455
|
+
const [rateLimit, setRateLimit] = useState3(void 0);
|
|
456
|
+
const [prevRateLimit, setPrevRateLimit] = useState3(void 0);
|
|
457
|
+
const [density, setDensity] = useState3(2);
|
|
458
|
+
const [prefsLoaded, setPrefsLoaded] = useState3(false);
|
|
459
|
+
const [ownerContext, setOwnerContext] = useState3("personal");
|
|
460
|
+
const [ownerAffiliations, setOwnerAffiliations] = useState3(["OWNER"]);
|
|
461
|
+
const [orgSwitcherOpen, setOrgSwitcherOpen] = useState3(false);
|
|
462
|
+
const [searchItems, setSearchItems] = useState3([]);
|
|
463
|
+
const [searchEndCursor, setSearchEndCursor] = useState3(null);
|
|
464
|
+
const [searchHasNextPage, setSearchHasNextPage] = useState3(false);
|
|
465
|
+
const [searchTotalCount, setSearchTotalCount] = useState3(0);
|
|
466
|
+
const [searchLoading, setSearchLoading] = useState3(false);
|
|
467
|
+
const [deleteMode, setDeleteMode] = useState3(false);
|
|
468
|
+
const [deleteTarget, setDeleteTarget] = useState3(null);
|
|
469
|
+
const [deleteCode, setDeleteCode] = useState3("");
|
|
470
|
+
const [typedCode, setTypedCode] = useState3("");
|
|
471
|
+
const [deleting, setDeleting] = useState3(false);
|
|
472
|
+
const [deleteError, setDeleteError] = useState3(null);
|
|
473
|
+
const [deleteConfirmStage, setDeleteConfirmStage] = useState3(false);
|
|
474
|
+
const [confirmFocus, setConfirmFocus] = useState3("delete");
|
|
475
|
+
const [archiveMode, setArchiveMode] = useState3(false);
|
|
476
|
+
const [archiveTarget, setArchiveTarget] = useState3(null);
|
|
477
|
+
const [archiving, setArchiving] = useState3(false);
|
|
478
|
+
const [archiveError, setArchiveError] = useState3(null);
|
|
479
|
+
const [archiveFocus, setArchiveFocus] = useState3("confirm");
|
|
480
|
+
const [syncMode, setSyncMode] = useState3(false);
|
|
481
|
+
const [syncTarget, setSyncTarget] = useState3(null);
|
|
482
|
+
const [syncing, setSyncing] = useState3(false);
|
|
483
|
+
const [syncError, setSyncError] = useState3(null);
|
|
484
|
+
const [syncFocus, setSyncFocus] = useState3("confirm");
|
|
485
|
+
const [infoMode, setInfoMode] = useState3(false);
|
|
486
|
+
const [logoutMode, setLogoutMode] = useState3(false);
|
|
487
|
+
const [logoutFocus, setLogoutFocus] = useState3("confirm");
|
|
488
|
+
const [logoutError, setLogoutError] = useState3(null);
|
|
456
489
|
function closeArchiveModal() {
|
|
457
490
|
setArchiveMode(false);
|
|
458
491
|
setArchiveTarget(null);
|
|
@@ -508,11 +541,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
508
541
|
setDeleteError("Failed to delete repository. Ensure delete_repo scope and admin permissions.");
|
|
509
542
|
}
|
|
510
543
|
}
|
|
511
|
-
const [filter, setFilter] =
|
|
512
|
-
const [filterMode, setFilterMode] =
|
|
513
|
-
const [sortKey, setSortKey] =
|
|
514
|
-
const [sortDir, setSortDir] =
|
|
515
|
-
const [forkTracking, setForkTracking] =
|
|
544
|
+
const [filter, setFilter] = useState3("");
|
|
545
|
+
const [filterMode, setFilterMode] = useState3(false);
|
|
546
|
+
const [sortKey, setSortKey] = useState3("updated");
|
|
547
|
+
const [sortDir, setSortDir] = useState3("desc");
|
|
548
|
+
const [forkTracking, setForkTracking] = useState3(true);
|
|
516
549
|
const sortFieldMap = {
|
|
517
550
|
"updated": "UPDATED_AT",
|
|
518
551
|
"pushed": "PUSHED_AT",
|
|
@@ -632,7 +665,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
632
665
|
setSearchLoading(false);
|
|
633
666
|
}
|
|
634
667
|
};
|
|
635
|
-
|
|
668
|
+
useEffect3(() => {
|
|
636
669
|
const ui = getUIPrefs();
|
|
637
670
|
if (ui.density !== void 0) setDensity(ui.density);
|
|
638
671
|
if (ui.sortKey && ["updated", "pushed", "name", "stars"].includes(ui.sortKey)) {
|
|
@@ -654,7 +687,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
654
687
|
}
|
|
655
688
|
setPrefsLoaded(true);
|
|
656
689
|
}, [onOrgContextChange]);
|
|
657
|
-
|
|
690
|
+
useEffect3(() => {
|
|
658
691
|
if (!prefsLoaded) return;
|
|
659
692
|
let policy = "cache-first";
|
|
660
693
|
const orgLogin2 = ownerContext !== "personal" ? ownerContext.login : void 0;
|
|
@@ -674,7 +707,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
674
707
|
setCursor(0);
|
|
675
708
|
fetchPage(null, true, false, void 0, policy);
|
|
676
709
|
}, [client, prefsLoaded, ownerContext, ownerAffiliations]);
|
|
677
|
-
|
|
710
|
+
useEffect3(() => {
|
|
678
711
|
if (!searchActive) {
|
|
679
712
|
if (items.length > 0) {
|
|
680
713
|
let policy = "cache-first";
|
|
@@ -713,7 +746,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
713
746
|
}
|
|
714
747
|
}
|
|
715
748
|
}, [sortKey, sortDir]);
|
|
716
|
-
|
|
749
|
+
useEffect3(() => {
|
|
717
750
|
if (viewerLogin && searchActive && !searchLoading && searchItems.length === 0) {
|
|
718
751
|
let policy = "cache-first";
|
|
719
752
|
try {
|
|
@@ -1105,12 +1138,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1105
1138
|
}, [filtered, sortKey, sortDir]);
|
|
1106
1139
|
const searchActive = filter.trim().length >= 3;
|
|
1107
1140
|
const visibleItems = searchActive ? searchItems : filteredAndSorted;
|
|
1108
|
-
|
|
1141
|
+
useEffect3(() => {
|
|
1109
1142
|
if (searchActive) {
|
|
1110
1143
|
addDebugMessage(`[State] searchActive=${searchActive}, searchItems=${searchItems.length}, visibleItems=${visibleItems.length}, filter="${filter}"`);
|
|
1111
1144
|
}
|
|
1112
1145
|
}, [searchActive, searchItems.length, visibleItems.length, filter]);
|
|
1113
|
-
|
|
1146
|
+
useEffect3(() => {
|
|
1114
1147
|
setCursor((c) => Math.min(c, Math.max(0, (searchActive ? searchItems.length : items.length) - 1)));
|
|
1115
1148
|
}, [searchActive, searchItems.length, items.length]);
|
|
1116
1149
|
const headerHeight = 2;
|
|
@@ -1131,7 +1164,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1131
1164
|
const end = Math.min(total, start + visibleRepos + buffer);
|
|
1132
1165
|
return { start, end };
|
|
1133
1166
|
}, [visibleItems.length, cursor, listHeight, spacingLines]);
|
|
1134
|
-
|
|
1167
|
+
useEffect3(() => {
|
|
1135
1168
|
const prefetchThreshold = Math.floor(visibleItems.length * 0.8);
|
|
1136
1169
|
const nearEnd = visibleItems.length > 0 && cursor >= prefetchThreshold;
|
|
1137
1170
|
if (searchActive) {
|
|
@@ -1153,81 +1186,88 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1153
1186
|
}
|
|
1154
1187
|
const lowRate = rateLimit && rateLimit.remaining <= Math.ceil(rateLimit.limit * 0.1);
|
|
1155
1188
|
const modalOpen = deleteMode || archiveMode || syncMode || logoutMode || infoMode;
|
|
1156
|
-
const headerBar = useMemo(() => /* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
/* @__PURE__ */
|
|
1159
|
-
/* @__PURE__ */
|
|
1189
|
+
const headerBar = useMemo(() => /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: [
|
|
1190
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
|
|
1191
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: modalOpen ? "gray" : void 0, dimColor: modalOpen ? true : void 0, children: " Repositories" }),
|
|
1192
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1160
1193
|
"(",
|
|
1161
1194
|
visibleItems.length,
|
|
1162
1195
|
"/",
|
|
1163
1196
|
searchActive ? searchTotalCount : totalCount,
|
|
1164
1197
|
")"
|
|
1165
1198
|
] }),
|
|
1166
|
-
(loading || searchLoading) && /* @__PURE__ */
|
|
1199
|
+
(loading || searchLoading) && /* @__PURE__ */ jsx6(Box5, { width: 2, flexShrink: 0, flexGrow: 0, marginLeft: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: /* @__PURE__ */ jsx6(SlowSpinner, {}) }) })
|
|
1167
1200
|
] }),
|
|
1168
|
-
rateLimit && /* @__PURE__ */
|
|
1201
|
+
rateLimit && /* @__PURE__ */ jsxs5(Text6, { color: lowRate ? "yellow" : "gray", children: [
|
|
1169
1202
|
"API: ",
|
|
1170
1203
|
rateLimit.remaining,
|
|
1171
1204
|
"/",
|
|
1172
1205
|
rateLimit.limit,
|
|
1173
|
-
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */
|
|
1206
|
+
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */ jsx6(Text6, { color: rateLimit.remaining < prevRateLimit ? "red" : "green", children: ` (${rateLimit.remaining - prevRateLimit > 0 ? "+" : ""}${rateLimit.remaining - prevRateLimit})` })
|
|
1174
1207
|
] })
|
|
1175
1208
|
] }), [visibleItems.length, searchActive, searchTotalCount, totalCount, loading, searchLoading, rateLimit, lowRate, modalOpen, prevRateLimit]);
|
|
1176
1209
|
if (error) {
|
|
1177
|
-
return /* @__PURE__ */
|
|
1178
|
-
/* @__PURE__ */
|
|
1179
|
-
|
|
1210
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: availableHeight, children: [
|
|
1211
|
+
/* @__PURE__ */ jsx6(Box5, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
|
|
1212
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: " Repositories" }),
|
|
1213
|
+
/* @__PURE__ */ jsx6(Text6, { color: "red", children: "(Error)" })
|
|
1214
|
+
] }) }),
|
|
1215
|
+
/* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: "red", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: /* @__PURE__ */ jsx6(Box5, { height: contentHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", children: [
|
|
1216
|
+
/* @__PURE__ */ jsx6(Text6, { color: "red", children: error }),
|
|
1217
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: "Press 'r' to retry or 'q' to quit" }) })
|
|
1218
|
+
] }) }) }),
|
|
1219
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", children: "Press 'r' to retry \u2022 'q' to quit" }) })
|
|
1180
1220
|
] });
|
|
1181
1221
|
}
|
|
1182
1222
|
if (loading && items.length === 0 || sortingLoading) {
|
|
1183
|
-
return /* @__PURE__ */
|
|
1184
|
-
/* @__PURE__ */
|
|
1185
|
-
/* @__PURE__ */
|
|
1186
|
-
/* @__PURE__ */
|
|
1223
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: availableHeight, children: [
|
|
1224
|
+
/* @__PURE__ */ jsx6(Box5, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
|
|
1225
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: " Repositories" }),
|
|
1226
|
+
/* @__PURE__ */ jsx6(Text6, { color: "gray", children: "(Loading...)" })
|
|
1187
1227
|
] }) }),
|
|
1188
|
-
/* @__PURE__ */
|
|
1189
|
-
/* @__PURE__ */
|
|
1190
|
-
/* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1228
|
+
/* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: /* @__PURE__ */ jsx6(Box5, { height: contentHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", alignItems: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", children: [
|
|
1229
|
+
/* @__PURE__ */ jsxs5(Box5, { height: 1, flexDirection: "row", children: [
|
|
1230
|
+
/* @__PURE__ */ jsx6(Box5, { width: 2, flexShrink: 0, flexGrow: 0, children: /* @__PURE__ */ jsx6(Text6, { color: "cyan", children: /* @__PURE__ */ jsx6(SlowSpinner, {}) }) }),
|
|
1231
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: refreshing ? "Refreshing..." : sortingLoading ? "Applying sort..." : "Loading repositories..." })
|
|
1192
1232
|
] }),
|
|
1193
|
-
/* @__PURE__ */
|
|
1233
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", children: refreshing ? "Fetching latest repository data" : sortingLoading ? `Sorting by ${sortKey} (${sortDir === "asc" ? "ascending" : "descending"})` : "Fetching your GitHub repositories" }) })
|
|
1194
1234
|
] }) }) }) }),
|
|
1195
|
-
/* @__PURE__ */
|
|
1235
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", children: "Please wait..." }) })
|
|
1196
1236
|
] });
|
|
1197
1237
|
}
|
|
1198
|
-
return /* @__PURE__ */
|
|
1238
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: availableHeight, children: [
|
|
1199
1239
|
headerBar,
|
|
1200
|
-
/* @__PURE__ */
|
|
1240
|
+
/* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: modalOpen ? "gray" : "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: deleteMode && deleteTarget ? (
|
|
1201
1241
|
// Centered modal; hide list content while modal is open
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1242
|
+
/* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1243
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Delete Confirmation" }),
|
|
1244
|
+
/* @__PURE__ */ jsx6(Text6, { color: "red", children: "\u26A0\uFE0F Delete repository?" }),
|
|
1245
|
+
/* @__PURE__ */ jsx6(Box5, { height: 2, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1206
1246
|
(() => {
|
|
1207
1247
|
const langName = deleteTarget.primaryLanguage?.name || "";
|
|
1208
1248
|
const langColor = deleteTarget.primaryLanguage?.color || "#666666";
|
|
1209
1249
|
let line1 = "";
|
|
1210
|
-
line1 +=
|
|
1211
|
-
if (deleteTarget.isPrivate) line1 +=
|
|
1212
|
-
if (deleteTarget.isArchived) line1 +=
|
|
1213
|
-
if (deleteTarget.isFork && deleteTarget.parent) line1 +=
|
|
1250
|
+
line1 += chalk3.white(deleteTarget.nameWithOwner);
|
|
1251
|
+
if (deleteTarget.isPrivate) line1 += chalk3.yellow(" Private");
|
|
1252
|
+
if (deleteTarget.isArchived) line1 += chalk3.gray.dim(" Archived");
|
|
1253
|
+
if (deleteTarget.isFork && deleteTarget.parent) line1 += chalk3.blue(` Fork of ${deleteTarget.parent.nameWithOwner}`);
|
|
1214
1254
|
let line2 = "";
|
|
1215
|
-
if (langName) line2 +=
|
|
1216
|
-
line2 +=
|
|
1217
|
-
return /* @__PURE__ */
|
|
1218
|
-
/* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1255
|
+
if (langName) line2 += chalk3.hex(langColor)("\u25CF ") + chalk3.gray(`${langName} `);
|
|
1256
|
+
line2 += chalk3.gray(`\u2605 ${deleteTarget.stargazerCount} \u2442 ${deleteTarget.forkCount} Updated ${formatDate(deleteTarget.updatedAt)}`);
|
|
1257
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1258
|
+
/* @__PURE__ */ jsx6(Text6, { children: line1 }),
|
|
1259
|
+
/* @__PURE__ */ jsx6(Text6, { children: line2 })
|
|
1220
1260
|
] });
|
|
1221
1261
|
})(),
|
|
1222
|
-
/* @__PURE__ */
|
|
1262
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
1223
1263
|
"Type ",
|
|
1224
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx6(Text6, { color: "yellow", bold: true, children: deleteCode }),
|
|
1225
1265
|
" to confirm."
|
|
1226
1266
|
] }) }),
|
|
1227
|
-
!deleteConfirmStage && /* @__PURE__ */
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1230
|
-
|
|
1267
|
+
!deleteConfirmStage && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
1268
|
+
/* @__PURE__ */ jsx6(Text6, { children: "Confirm code: " }),
|
|
1269
|
+
/* @__PURE__ */ jsx6(
|
|
1270
|
+
TextInput2,
|
|
1231
1271
|
{
|
|
1232
1272
|
value: typedCode,
|
|
1233
1273
|
onChange: (v) => {
|
|
@@ -1253,11 +1293,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1253
1293
|
}
|
|
1254
1294
|
)
|
|
1255
1295
|
] }),
|
|
1256
|
-
deleteConfirmStage && /* @__PURE__ */
|
|
1257
|
-
/* @__PURE__ */
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
|
|
1296
|
+
deleteConfirmStage && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
1297
|
+
/* @__PURE__ */ jsx6(Text6, { color: "red", children: "This action will permanently delete the repository. This cannot be undone." }),
|
|
1298
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1299
|
+
/* @__PURE__ */ jsx6(
|
|
1300
|
+
Box5,
|
|
1261
1301
|
{
|
|
1262
1302
|
borderStyle: "round",
|
|
1263
1303
|
borderColor: "red",
|
|
@@ -1266,11 +1306,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1266
1306
|
alignItems: "center",
|
|
1267
1307
|
justifyContent: "center",
|
|
1268
1308
|
flexDirection: "column",
|
|
1269
|
-
children: /* @__PURE__ */
|
|
1309
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: confirmFocus === "delete" ? chalk3.bgRed.white.bold(" Delete ") : chalk3.red.bold("Delete") })
|
|
1270
1310
|
}
|
|
1271
1311
|
),
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
|
|
1312
|
+
/* @__PURE__ */ jsx6(
|
|
1313
|
+
Box5,
|
|
1274
1314
|
{
|
|
1275
1315
|
borderStyle: "round",
|
|
1276
1316
|
borderColor: confirmFocus === "cancel" ? "white" : "gray",
|
|
@@ -1279,17 +1319,17 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1279
1319
|
alignItems: "center",
|
|
1280
1320
|
justifyContent: "center",
|
|
1281
1321
|
flexDirection: "column",
|
|
1282
|
-
children: /* @__PURE__ */
|
|
1322
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: confirmFocus === "cancel" ? chalk3.bgGray.white.bold(" Cancel ") : chalk3.gray.bold("Cancel") })
|
|
1283
1323
|
}
|
|
1284
1324
|
)
|
|
1285
1325
|
] }),
|
|
1286
|
-
/* @__PURE__ */
|
|
1326
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1287
1327
|
"Press Enter to ",
|
|
1288
1328
|
confirmFocus === "delete" ? "Delete" : "Cancel",
|
|
1289
1329
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1290
1330
|
] }) }),
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
|
|
1331
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1332
|
+
TextInput2,
|
|
1293
1333
|
{
|
|
1294
1334
|
value: "",
|
|
1295
1335
|
onChange: () => {
|
|
@@ -1302,18 +1342,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1302
1342
|
}
|
|
1303
1343
|
) })
|
|
1304
1344
|
] }),
|
|
1305
|
-
deleteError && /* @__PURE__ */
|
|
1306
|
-
deleting && /* @__PURE__ */
|
|
1345
|
+
deleteError && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "magenta", children: deleteError }) }),
|
|
1346
|
+
deleting && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "Deleting..." }) })
|
|
1307
1347
|
] }) })
|
|
1308
|
-
) : archiveMode && archiveTarget ? /* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
/* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
|
|
1348
|
+
) : archiveMode && archiveTarget ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: archiveTarget.isArchived ? "green" : "yellow", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1349
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: archiveTarget.isArchived ? "Unarchive Confirmation" : "Archive Confirmation" }),
|
|
1350
|
+
/* @__PURE__ */ jsx6(Text6, { color: archiveTarget.isArchived ? "green" : "yellow", children: archiveTarget.isArchived ? "\u21BA Unarchive repository?" : "\u26A0\uFE0F Archive repository?" }),
|
|
1351
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1352
|
+
/* @__PURE__ */ jsx6(Text6, { children: archiveTarget.nameWithOwner }),
|
|
1353
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { children: archiveTarget.isArchived ? "This will make the repository active again." : "This will make the repository read-only." }) }),
|
|
1354
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1355
|
+
/* @__PURE__ */ jsx6(
|
|
1356
|
+
Box5,
|
|
1317
1357
|
{
|
|
1318
1358
|
borderStyle: "round",
|
|
1319
1359
|
borderColor: archiveTarget.isArchived ? "green" : "yellow",
|
|
@@ -1322,11 +1362,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1322
1362
|
alignItems: "center",
|
|
1323
1363
|
justifyContent: "center",
|
|
1324
1364
|
flexDirection: "column",
|
|
1325
|
-
children: /* @__PURE__ */
|
|
1365
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: archiveFocus === "confirm" ? chalk3.bgGreen.white.bold(` ${archiveTarget.isArchived ? "Unarchive" : "Archive"} `) : chalk3.bold[archiveTarget.isArchived ? "green" : "yellow"](archiveTarget.isArchived ? "Unarchive" : "Archive") })
|
|
1326
1366
|
}
|
|
1327
1367
|
),
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
|
|
1368
|
+
/* @__PURE__ */ jsx6(
|
|
1369
|
+
Box5,
|
|
1330
1370
|
{
|
|
1331
1371
|
borderStyle: "round",
|
|
1332
1372
|
borderColor: archiveFocus === "cancel" ? "white" : "gray",
|
|
@@ -1335,17 +1375,17 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1335
1375
|
alignItems: "center",
|
|
1336
1376
|
justifyContent: "center",
|
|
1337
1377
|
flexDirection: "column",
|
|
1338
|
-
children: /* @__PURE__ */
|
|
1378
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: archiveFocus === "cancel" ? chalk3.bgGray.white.bold(" Cancel ") : chalk3.gray.bold("Cancel") })
|
|
1339
1379
|
}
|
|
1340
1380
|
)
|
|
1341
1381
|
] }),
|
|
1342
|
-
/* @__PURE__ */
|
|
1382
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1343
1383
|
"Press Enter to ",
|
|
1344
1384
|
archiveFocus === "confirm" ? archiveTarget.isArchived ? "Unarchive" : "Archive" : "Cancel",
|
|
1345
1385
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1346
1386
|
] }) }),
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
|
|
1387
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1388
|
+
TextInput2,
|
|
1349
1389
|
{
|
|
1350
1390
|
value: "",
|
|
1351
1391
|
onChange: () => {
|
|
@@ -1372,21 +1412,21 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1372
1412
|
}
|
|
1373
1413
|
}
|
|
1374
1414
|
) }),
|
|
1375
|
-
archiveError && /* @__PURE__ */
|
|
1376
|
-
archiving && /* @__PURE__ */
|
|
1377
|
-
] }) }) : syncMode && syncTarget ? /* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1380
|
-
/* @__PURE__ */
|
|
1381
|
-
/* @__PURE__ */
|
|
1382
|
-
syncTarget.parent && /* @__PURE__ */
|
|
1415
|
+
archiveError && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "magenta", children: archiveError }) }),
|
|
1416
|
+
archiving && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: archiveTarget.isArchived ? "Unarchiving..." : "Archiving..." }) })
|
|
1417
|
+
] }) }) : syncMode && syncTarget ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1418
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Sync Fork Confirmation" }),
|
|
1419
|
+
/* @__PURE__ */ jsx6(Text6, { color: "blue", children: "\u27F2 Sync fork with upstream?" }),
|
|
1420
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1421
|
+
/* @__PURE__ */ jsx6(Text6, { children: syncTarget.nameWithOwner }),
|
|
1422
|
+
syncTarget.parent && /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1383
1423
|
"Upstream: ",
|
|
1384
1424
|
syncTarget.parent.nameWithOwner
|
|
1385
1425
|
] }),
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
|
|
1426
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { children: "This will merge upstream changes into your fork." }) }),
|
|
1427
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1428
|
+
/* @__PURE__ */ jsx6(
|
|
1429
|
+
Box5,
|
|
1390
1430
|
{
|
|
1391
1431
|
borderStyle: "round",
|
|
1392
1432
|
borderColor: "blue",
|
|
@@ -1395,11 +1435,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1395
1435
|
alignItems: "center",
|
|
1396
1436
|
justifyContent: "center",
|
|
1397
1437
|
flexDirection: "column",
|
|
1398
|
-
children: /* @__PURE__ */
|
|
1438
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: syncFocus === "confirm" ? chalk3.bgBlue.white.bold(" Sync ") : chalk3.blue.bold("Sync") })
|
|
1399
1439
|
}
|
|
1400
1440
|
),
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
|
|
1441
|
+
/* @__PURE__ */ jsx6(
|
|
1442
|
+
Box5,
|
|
1403
1443
|
{
|
|
1404
1444
|
borderStyle: "round",
|
|
1405
1445
|
borderColor: syncFocus === "cancel" ? "white" : "gray",
|
|
@@ -1408,17 +1448,17 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1408
1448
|
alignItems: "center",
|
|
1409
1449
|
justifyContent: "center",
|
|
1410
1450
|
flexDirection: "column",
|
|
1411
|
-
children: /* @__PURE__ */
|
|
1451
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: syncFocus === "cancel" ? chalk3.bgGray.white.bold(" Cancel ") : chalk3.gray.bold("Cancel") })
|
|
1412
1452
|
}
|
|
1413
1453
|
)
|
|
1414
1454
|
] }),
|
|
1415
|
-
/* @__PURE__ */
|
|
1455
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1416
1456
|
"Press Enter to ",
|
|
1417
1457
|
syncFocus === "confirm" ? "Sync" : "Cancel",
|
|
1418
1458
|
" \u2022 y to confirm \u2022 c to cancel"
|
|
1419
1459
|
] }) }),
|
|
1420
|
-
/* @__PURE__ */
|
|
1421
|
-
|
|
1460
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(
|
|
1461
|
+
TextInput2,
|
|
1422
1462
|
{
|
|
1423
1463
|
value: "",
|
|
1424
1464
|
onChange: () => {
|
|
@@ -1459,14 +1499,14 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1459
1499
|
}
|
|
1460
1500
|
}
|
|
1461
1501
|
) }),
|
|
1462
|
-
syncError && /* @__PURE__ */
|
|
1463
|
-
syncing && /* @__PURE__ */
|
|
1464
|
-
] }) }) : logoutMode ? /* @__PURE__ */
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1467
|
-
/* @__PURE__ */
|
|
1468
|
-
/* @__PURE__ */
|
|
1469
|
-
|
|
1502
|
+
syncError && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "magenta", children: syncError }) }),
|
|
1503
|
+
syncing && /* @__PURE__ */ jsx6(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "Syncing..." }) })
|
|
1504
|
+
] }) }) : logoutMode ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1505
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Logout Confirmation" }),
|
|
1506
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "Are you sure you want to log out?" }),
|
|
1507
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1508
|
+
/* @__PURE__ */ jsx6(
|
|
1509
|
+
Box5,
|
|
1470
1510
|
{
|
|
1471
1511
|
borderStyle: "round",
|
|
1472
1512
|
borderColor: "cyan",
|
|
@@ -1475,11 +1515,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1475
1515
|
alignItems: "center",
|
|
1476
1516
|
justifyContent: "center",
|
|
1477
1517
|
flexDirection: "column",
|
|
1478
|
-
children: /* @__PURE__ */
|
|
1518
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: logoutFocus === "confirm" ? chalk3.bgCyan.white.bold(" Logout ") : chalk3.cyan.bold("Logout") })
|
|
1479
1519
|
}
|
|
1480
1520
|
),
|
|
1481
|
-
/* @__PURE__ */
|
|
1482
|
-
|
|
1521
|
+
/* @__PURE__ */ jsx6(
|
|
1522
|
+
Box5,
|
|
1483
1523
|
{
|
|
1484
1524
|
borderStyle: "round",
|
|
1485
1525
|
borderColor: logoutFocus === "cancel" ? "white" : "gray",
|
|
@@ -1488,16 +1528,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1488
1528
|
alignItems: "center",
|
|
1489
1529
|
justifyContent: "center",
|
|
1490
1530
|
flexDirection: "column",
|
|
1491
|
-
children: /* @__PURE__ */
|
|
1531
|
+
children: /* @__PURE__ */ jsx6(Text6, { children: logoutFocus === "cancel" ? chalk3.bgGray.white.bold(" Cancel ") : chalk3.gray.bold("Cancel") })
|
|
1492
1532
|
}
|
|
1493
1533
|
)
|
|
1494
1534
|
] }),
|
|
1495
|
-
/* @__PURE__ */
|
|
1535
|
+
/* @__PURE__ */ jsx6(Box5, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1496
1536
|
"Press Enter to ",
|
|
1497
1537
|
logoutFocus === "confirm" ? "Logout" : "Cancel",
|
|
1498
1538
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1499
1539
|
] }) })
|
|
1500
|
-
] }) }) : orgSwitcherOpen ? /* @__PURE__ */
|
|
1540
|
+
] }) }) : orgSwitcherOpen ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx6(
|
|
1501
1541
|
OrgSwitcher,
|
|
1502
1542
|
{
|
|
1503
1543
|
token,
|
|
@@ -1505,75 +1545,75 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1505
1545
|
onSelect: handleOrgContextChange,
|
|
1506
1546
|
onClose: () => setOrgSwitcherOpen(false)
|
|
1507
1547
|
}
|
|
1508
|
-
) }) : infoMode ? /* @__PURE__ */
|
|
1548
|
+
) }) : infoMode ? /* @__PURE__ */ jsx6(Box5, { height: contentHeight, alignItems: "center", justifyContent: "center", children: (() => {
|
|
1509
1549
|
const repo = visibleItems[cursor];
|
|
1510
|
-
if (!repo) return /* @__PURE__ */
|
|
1550
|
+
if (!repo) return /* @__PURE__ */ jsx6(Text6, { color: "red", children: "No repository selected." });
|
|
1511
1551
|
const langName = repo.primaryLanguage?.name || "N/A";
|
|
1512
1552
|
const langColor = repo.primaryLanguage?.color || "#666666";
|
|
1513
|
-
return /* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
1515
|
-
/* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
repo.description && /* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
repo.isPrivate ?
|
|
1521
|
-
repo.isArchived ?
|
|
1522
|
-
repo.isFork ?
|
|
1553
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 90), children: [
|
|
1554
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Repository Info" }),
|
|
1555
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1556
|
+
/* @__PURE__ */ jsx6(Text6, { children: chalk3.bold(repo.nameWithOwner) }),
|
|
1557
|
+
repo.description && /* @__PURE__ */ jsx6(Text6, { color: "gray", children: repo.description }),
|
|
1558
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1559
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
1560
|
+
repo.isPrivate ? chalk3.yellow("Private") : chalk3.green("Public"),
|
|
1561
|
+
repo.isArchived ? chalk3.gray(" Archived") : "",
|
|
1562
|
+
repo.isFork ? chalk3.blue(" Fork") : ""
|
|
1523
1563
|
] }),
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1526
|
-
|
|
1527
|
-
|
|
1564
|
+
/* @__PURE__ */ jsx6(Text6, { children: chalk3.gray(`\u2605 ${repo.stargazerCount} \u2442 ${repo.forkCount}`) }),
|
|
1565
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
1566
|
+
chalk3.hex(langColor)(`\u25CF `),
|
|
1567
|
+
chalk3.gray(`${langName}`)
|
|
1528
1568
|
] }),
|
|
1529
|
-
/* @__PURE__ */
|
|
1569
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1530
1570
|
"Updated: ",
|
|
1531
1571
|
formatDate(repo.updatedAt),
|
|
1532
1572
|
" \u2022 Pushed: ",
|
|
1533
1573
|
formatDate(repo.pushedAt)
|
|
1534
1574
|
] }),
|
|
1535
|
-
/* @__PURE__ */
|
|
1575
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "gray", children: [
|
|
1536
1576
|
"Size: ",
|
|
1537
1577
|
repo.diskUsage,
|
|
1538
1578
|
" KB"
|
|
1539
1579
|
] }),
|
|
1540
|
-
/* @__PURE__ */
|
|
1541
|
-
/* @__PURE__ */
|
|
1580
|
+
/* @__PURE__ */ jsx6(Box5, { height: 1, children: /* @__PURE__ */ jsx6(Text6, { children: " " }) }),
|
|
1581
|
+
/* @__PURE__ */ jsx6(Text6, { color: "gray", children: "Press Esc or I to close" })
|
|
1542
1582
|
] });
|
|
1543
|
-
})() }) : /* @__PURE__ */
|
|
1544
|
-
/* @__PURE__ */
|
|
1545
|
-
/* @__PURE__ */
|
|
1546
|
-
/* @__PURE__ */
|
|
1583
|
+
})() }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1584
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 2, marginBottom: 1, children: [
|
|
1585
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", bold: true, children: ownerContext === "personal" ? "Personal Account" : `Organization: ${ownerContext.name || ownerContext.login}` }),
|
|
1586
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "gray", dimColor: true, children: [
|
|
1547
1587
|
"Sort: ",
|
|
1548
1588
|
sortKey,
|
|
1549
1589
|
" ",
|
|
1550
1590
|
sortDir === "asc" ? "\u2191" : "\u2193"
|
|
1551
1591
|
] }),
|
|
1552
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "gray", dimColor: true, children: [
|
|
1553
1593
|
"Forks - Commits Behind: ",
|
|
1554
1594
|
forkTracking ? "ON" : "OFF"
|
|
1555
1595
|
] }),
|
|
1556
|
-
filter && !searchActive && /* @__PURE__ */
|
|
1596
|
+
filter && !searchActive && /* @__PURE__ */ jsxs5(Text6, { color: "cyan", children: [
|
|
1557
1597
|
'Filter: "',
|
|
1558
1598
|
filter,
|
|
1559
1599
|
'"'
|
|
1560
1600
|
] }),
|
|
1561
|
-
searchActive && /* @__PURE__ */
|
|
1562
|
-
/* @__PURE__ */
|
|
1601
|
+
searchActive && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1602
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "cyan", children: [
|
|
1563
1603
|
'Search: "',
|
|
1564
1604
|
filter.trim(),
|
|
1565
1605
|
'"'
|
|
1566
1606
|
] }),
|
|
1567
|
-
searchLoading && /* @__PURE__ */
|
|
1568
|
-
/* @__PURE__ */
|
|
1607
|
+
searchLoading && /* @__PURE__ */ jsx6(Box5, { marginLeft: 1, children: /* @__PURE__ */ jsxs5(Text6, { color: "cyan", children: [
|
|
1608
|
+
/* @__PURE__ */ jsx6(SlowSpinner, {}),
|
|
1569
1609
|
" Searching\u2026"
|
|
1570
1610
|
] }) })
|
|
1571
1611
|
] })
|
|
1572
1612
|
] }),
|
|
1573
|
-
filterMode && /* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
|
|
1613
|
+
filterMode && /* @__PURE__ */ jsxs5(Box5, { marginBottom: 1, children: [
|
|
1614
|
+
/* @__PURE__ */ jsx6(Text6, { children: "Filter: " }),
|
|
1615
|
+
/* @__PURE__ */ jsx6(
|
|
1616
|
+
TextInput2,
|
|
1577
1617
|
{
|
|
1578
1618
|
value: filter,
|
|
1579
1619
|
onChange: (val) => {
|
|
@@ -1612,10 +1652,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1612
1652
|
}
|
|
1613
1653
|
)
|
|
1614
1654
|
] }),
|
|
1615
|
-
/* @__PURE__ */
|
|
1616
|
-
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */
|
|
1655
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: listHeight, children: [
|
|
1656
|
+
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */ jsx6(Box5, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: "Type at least 3 characters to search" }) }) : visibleItems.slice(windowed.start, windowed.end).map((repo, i) => {
|
|
1617
1657
|
const idx = windowed.start + i;
|
|
1618
|
-
return /* @__PURE__ */
|
|
1658
|
+
return /* @__PURE__ */ jsx6(
|
|
1619
1659
|
RepoRow,
|
|
1620
1660
|
{
|
|
1621
1661
|
repo,
|
|
@@ -1628,43 +1668,43 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1628
1668
|
repo.nameWithOwner
|
|
1629
1669
|
);
|
|
1630
1670
|
}),
|
|
1631
|
-
loadingMore && hasNextPage && /* @__PURE__ */
|
|
1632
|
-
/* @__PURE__ */
|
|
1633
|
-
/* @__PURE__ */
|
|
1671
|
+
loadingMore && hasNextPage && /* @__PURE__ */ jsx6(Box5, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", children: [
|
|
1672
|
+
/* @__PURE__ */ jsx6(Box5, { width: 2, flexShrink: 0, flexGrow: 0, marginRight: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "cyan", children: /* @__PURE__ */ jsx6(SlowSpinner, {}) }) }),
|
|
1673
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "Loading more repositories..." })
|
|
1634
1674
|
] }) }),
|
|
1635
|
-
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */
|
|
1675
|
+
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */ jsx6(Box5, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: searchActive ? "No repositories match your search" : filter ? "No repositories match your filter" : "No repositories found" }) })
|
|
1636
1676
|
] })
|
|
1637
1677
|
] }) }),
|
|
1638
|
-
/* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
/* @__PURE__ */
|
|
1678
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx6(Box5, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: modalOpen ? true : void 0, children: "\u2191\u2193 Navigate \u2022 Ctrl+G Top \u2022 G Bottom \u2022 / Filter \u2022 W Org Switcher \u2022 S Sort \u2022 D Direction \u2022 T Density \u2022 F Forks \u2022 \u23CE/O Open" }) }),
|
|
1680
|
+
/* @__PURE__ */ jsx6(Box5, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: modalOpen ? true : void 0, children: "Del/Ctrl+Backspace Delete \u2022 Ctrl+A Un/Archive \u2022 Ctrl+U Sync Fork \u2022 I Info \u2022 Ctrl+I Cache \u2022 Ctrl+L Logout \u2022 R Refresh \u2022 Q Quit" }) })
|
|
1641
1681
|
] }),
|
|
1642
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
debugMessages.length === 0 ? /* @__PURE__ */
|
|
1682
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [
|
|
1683
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: "yellow", children: "Debug Messages:" }),
|
|
1684
|
+
debugMessages.length === 0 ? /* @__PURE__ */ jsx6(Text6, { color: "gray", children: "No debug messages yet..." }) : debugMessages.map((msg, i) => /* @__PURE__ */ jsx6(Text6, { color: "gray", children: msg }, i))
|
|
1645
1685
|
] })
|
|
1646
1686
|
] });
|
|
1647
1687
|
}
|
|
1648
1688
|
|
|
1649
1689
|
// src/ui/App.tsx
|
|
1650
|
-
import { jsx as
|
|
1690
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1651
1691
|
var packageJson = require_package();
|
|
1652
1692
|
function App() {
|
|
1653
1693
|
const { exit } = useApp2();
|
|
1654
1694
|
const { stdout } = useStdout2();
|
|
1655
|
-
const [mode, setMode] =
|
|
1656
|
-
const [token, setToken] =
|
|
1657
|
-
const [input, setInput] =
|
|
1658
|
-
const [error, setError] =
|
|
1659
|
-
const [viewer, setViewer] =
|
|
1660
|
-
const [rateLimitReset, setRateLimitReset] =
|
|
1661
|
-
const [orgContext, setOrgContext] =
|
|
1662
|
-
const [dims, setDims] =
|
|
1695
|
+
const [mode, setMode] = useState4("checking");
|
|
1696
|
+
const [token, setToken] = useState4(null);
|
|
1697
|
+
const [input, setInput] = useState4("");
|
|
1698
|
+
const [error, setError] = useState4(null);
|
|
1699
|
+
const [viewer, setViewer] = useState4(null);
|
|
1700
|
+
const [rateLimitReset, setRateLimitReset] = useState4(null);
|
|
1701
|
+
const [orgContext, setOrgContext] = useState4("personal");
|
|
1702
|
+
const [dims, setDims] = useState4(() => {
|
|
1663
1703
|
const cols = stdout?.columns ?? 100;
|
|
1664
1704
|
const rows = stdout?.rows ?? 30;
|
|
1665
1705
|
return { cols, rows };
|
|
1666
1706
|
});
|
|
1667
|
-
|
|
1707
|
+
useEffect4(() => {
|
|
1668
1708
|
if (!stdout) return;
|
|
1669
1709
|
const onResize = () => {
|
|
1670
1710
|
const cols = stdout.columns ?? 100;
|
|
@@ -1676,7 +1716,7 @@ function App() {
|
|
|
1676
1716
|
stdout.off?.("resize", onResize);
|
|
1677
1717
|
};
|
|
1678
1718
|
}, [stdout]);
|
|
1679
|
-
|
|
1719
|
+
useEffect4(() => {
|
|
1680
1720
|
const env = getTokenFromEnv();
|
|
1681
1721
|
const stored = getStoredToken();
|
|
1682
1722
|
if (env) {
|
|
@@ -1689,7 +1729,7 @@ function App() {
|
|
|
1689
1729
|
setMode("prompt");
|
|
1690
1730
|
}
|
|
1691
1731
|
}, []);
|
|
1692
|
-
|
|
1732
|
+
useEffect4(() => {
|
|
1693
1733
|
(async () => {
|
|
1694
1734
|
if (mode !== "validating" || !token) return;
|
|
1695
1735
|
const timeoutId = setTimeout(() => {
|
|
@@ -1800,19 +1840,19 @@ function App() {
|
|
|
1800
1840
|
}
|
|
1801
1841
|
});
|
|
1802
1842
|
const verticalPadding = Math.floor(dims.rows * 0.15);
|
|
1803
|
-
const header = useMemo2(() => /* @__PURE__ */
|
|
1804
|
-
/* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
1843
|
+
const header = useMemo2(() => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [
|
|
1844
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", gap: 1, children: [
|
|
1845
|
+
/* @__PURE__ */ jsxs6(Text7, { bold: true, color: "cyan", children: [
|
|
1806
1846
|
" ",
|
|
1807
1847
|
"GitHub Repository Manager"
|
|
1808
1848
|
] }),
|
|
1809
|
-
/* @__PURE__ */
|
|
1849
|
+
/* @__PURE__ */ jsxs6(Text7, { color: "gray", dimColor: true, children: [
|
|
1810
1850
|
"v",
|
|
1811
1851
|
packageJson.version
|
|
1812
1852
|
] }),
|
|
1813
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
1853
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsx7(Text7, { backgroundColor: "blue", color: "white", children: " debug mode " })
|
|
1814
1854
|
] }),
|
|
1815
|
-
viewer && /* @__PURE__ */
|
|
1855
|
+
viewer && /* @__PURE__ */ jsx7(Text7, { color: "gray", children: orgContext !== "personal" && orgContext.login ? `${orgContext.login}/@${viewer} ` : `@${viewer} ` })
|
|
1816
1856
|
] }), [viewer, orgContext]);
|
|
1817
1857
|
if (mode === "rate_limited") {
|
|
1818
1858
|
const formatResetTime = (resetTime) => {
|
|
@@ -1835,56 +1875,56 @@ function App() {
|
|
|
1835
1875
|
return "Unknown";
|
|
1836
1876
|
}
|
|
1837
1877
|
};
|
|
1838
|
-
return /* @__PURE__ */
|
|
1878
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
1839
1879
|
header,
|
|
1840
|
-
/* @__PURE__ */
|
|
1841
|
-
/* @__PURE__ */
|
|
1842
|
-
/* @__PURE__ */
|
|
1843
|
-
/* @__PURE__ */
|
|
1844
|
-
rateLimitReset && /* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
1880
|
+
/* @__PURE__ */ jsx7(Box6, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs6(Box6, { borderStyle: "single", borderColor: "yellow", paddingX: 3, paddingY: 2, flexDirection: "column", width: Math.min(dims.cols - 8, 80), children: [
|
|
1881
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "yellow", marginBottom: 1, children: "\u26A0\uFE0F Rate Limit Exceeded" }),
|
|
1882
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", marginBottom: 1, children: "You've hit GitHub's API rate limit for your token." }),
|
|
1883
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", marginBottom: 1, children: "This happens when you make too many requests in a short time." }),
|
|
1884
|
+
rateLimitReset && /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, marginBottom: 1, children: [
|
|
1885
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1886
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "Reset in:" }),
|
|
1847
1887
|
" ",
|
|
1848
|
-
/* @__PURE__ */
|
|
1888
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: formatResetTime(rateLimitReset) })
|
|
1849
1889
|
] }),
|
|
1850
|
-
/* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ jsxs6(Text7, { color: "gray", dimColor: true, children: [
|
|
1851
1891
|
"(",
|
|
1852
1892
|
new Date(rateLimitReset).toLocaleTimeString(),
|
|
1853
1893
|
")"
|
|
1854
1894
|
] })
|
|
1855
1895
|
] }),
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
/* @__PURE__ */
|
|
1859
|
-
/* @__PURE__ */
|
|
1860
|
-
/* @__PURE__ */
|
|
1896
|
+
/* @__PURE__ */ jsxs6(Box6, { marginTop: 2, flexDirection: "column", gap: 1, children: [
|
|
1897
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "What would you like to do?" }),
|
|
1898
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingLeft: 2, children: [
|
|
1899
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1900
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", bold: true, children: "r" }),
|
|
1861
1901
|
" - Retry now ",
|
|
1862
1902
|
rateLimitReset && formatResetTime(rateLimitReset) !== "Now (should be reset)" ? "(likely to fail until reset)" : "(should work now)"
|
|
1863
1903
|
] }),
|
|
1864
|
-
/* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
1904
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1905
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", bold: true, children: "l" }),
|
|
1866
1906
|
" - Logout and use a different token"
|
|
1867
1907
|
] }),
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
1908
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1909
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", bold: true, children: "q/Esc" }),
|
|
1870
1910
|
" - Quit application"
|
|
1871
1911
|
] })
|
|
1872
1912
|
] })
|
|
1873
1913
|
] }),
|
|
1874
|
-
/* @__PURE__ */
|
|
1914
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", dimColor: true, marginTop: 2, children: "Tip: Using multiple tokens or waiting between requests can help avoid rate limits." })
|
|
1875
1915
|
] }) })
|
|
1876
1916
|
] });
|
|
1877
1917
|
}
|
|
1878
1918
|
if (mode === "prompt") {
|
|
1879
|
-
return /* @__PURE__ */
|
|
1919
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
1880
1920
|
header,
|
|
1881
|
-
/* @__PURE__ */
|
|
1882
|
-
/* @__PURE__ */
|
|
1883
|
-
/* @__PURE__ */
|
|
1884
|
-
/* @__PURE__ */
|
|
1885
|
-
/* @__PURE__ */
|
|
1886
|
-
/* @__PURE__ */
|
|
1887
|
-
|
|
1921
|
+
/* @__PURE__ */ jsx7(Box6, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs6(Box6, { borderStyle: "single", borderColor: "cyan", paddingX: 2, paddingY: 1, flexDirection: "column", children: [
|
|
1922
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, marginBottom: 1, children: "Authentication Required" }),
|
|
1923
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", marginBottom: 1, children: "Enter your GitHub Personal Access Token" }),
|
|
1924
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1925
|
+
/* @__PURE__ */ jsx7(Text7, { children: "Token: " }),
|
|
1926
|
+
/* @__PURE__ */ jsx7(
|
|
1927
|
+
TextInput3,
|
|
1888
1928
|
{
|
|
1889
1929
|
value: input,
|
|
1890
1930
|
onChange: setInput,
|
|
@@ -1893,30 +1933,30 @@ function App() {
|
|
|
1893
1933
|
}
|
|
1894
1934
|
)
|
|
1895
1935
|
] }),
|
|
1896
|
-
error && /* @__PURE__ */
|
|
1897
|
-
/* @__PURE__ */
|
|
1898
|
-
/* @__PURE__ */
|
|
1936
|
+
error && /* @__PURE__ */ jsx7(Text7, { color: "red", marginTop: 1, children: error }),
|
|
1937
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", dimColor: true, marginTop: 1, children: "The token will be stored securely in your local config" }),
|
|
1938
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to quit" })
|
|
1899
1939
|
] }) })
|
|
1900
1940
|
] });
|
|
1901
1941
|
}
|
|
1902
1942
|
if (mode === "validating" || mode === "checking") {
|
|
1903
|
-
return /* @__PURE__ */
|
|
1943
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
1904
1944
|
header,
|
|
1905
|
-
/* @__PURE__ */
|
|
1906
|
-
/* @__PURE__ */
|
|
1907
|
-
mode === "validating" && /* @__PURE__ */
|
|
1945
|
+
/* @__PURE__ */ jsx7(Box6, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", alignItems: "center", children: [
|
|
1946
|
+
/* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "Validating token..." }),
|
|
1947
|
+
mode === "validating" && /* @__PURE__ */ jsx7(Text7, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to cancel" })
|
|
1908
1948
|
] }) })
|
|
1909
1949
|
] });
|
|
1910
1950
|
}
|
|
1911
1951
|
if (mode === "error") {
|
|
1912
|
-
return /* @__PURE__ */
|
|
1952
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
1913
1953
|
header,
|
|
1914
|
-
/* @__PURE__ */
|
|
1954
|
+
/* @__PURE__ */ jsx7(Box6, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx7(Text7, { color: "red", children: error ?? "Unexpected error" }) })
|
|
1915
1955
|
] });
|
|
1916
1956
|
}
|
|
1917
|
-
return /* @__PURE__ */
|
|
1957
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
1918
1958
|
header,
|
|
1919
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsx7(
|
|
1920
1960
|
RepoList,
|
|
1921
1961
|
{
|
|
1922
1962
|
token,
|
|
@@ -1930,7 +1970,7 @@ function App() {
|
|
|
1930
1970
|
}
|
|
1931
1971
|
|
|
1932
1972
|
// src/index.tsx
|
|
1933
|
-
import { jsx as
|
|
1973
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1934
1974
|
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
1935
1975
|
process.stderr.write("\u{1F41B} Debug mode enabled\n");
|
|
1936
1976
|
}
|
|
@@ -1943,8 +1983,8 @@ process.on("unhandledRejection", (reason) => {
|
|
|
1943
1983
|
process.exit(1);
|
|
1944
1984
|
});
|
|
1945
1985
|
render(
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
/* @__PURE__ */
|
|
1986
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1987
|
+
/* @__PURE__ */ jsx8(App, {}),
|
|
1988
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray" })
|
|
1949
1989
|
] })
|
|
1950
1990
|
);
|