gh-manager-cli 1.20.0 → 1.21.0
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 +14 -3
- package/dist/index.js +604 -365
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ var require_package = __commonJS({
|
|
|
30
30
|
"package.json"(exports, module) {
|
|
31
31
|
module.exports = {
|
|
32
32
|
name: "gh-manager-cli",
|
|
33
|
-
version: "1.
|
|
33
|
+
version: "1.21.0",
|
|
34
34
|
private: false,
|
|
35
35
|
description: "Interactive CLI to manage your GitHub repos (personal) with Ink",
|
|
36
36
|
license: "MIT",
|
|
@@ -76,6 +76,7 @@ var require_package = __commonJS({
|
|
|
76
76
|
"@octokit/graphql": "^9.0.1",
|
|
77
77
|
"apollo3-cache-persist": "^0.14.1",
|
|
78
78
|
chalk: "^5.6.0",
|
|
79
|
+
clipboardy: "^4.0.0",
|
|
79
80
|
dotenv: "^17.2.1",
|
|
80
81
|
"env-paths": "^3.0.0",
|
|
81
82
|
graphql: "^16.11.0",
|
|
@@ -155,12 +156,12 @@ var require_package = __commonJS({
|
|
|
155
156
|
|
|
156
157
|
// src/index.tsx
|
|
157
158
|
var import_package = __toESM(require_package(), 1);
|
|
158
|
-
import { render, Box as
|
|
159
|
+
import { render, Box as Box19, Text as Text20 } from "ink";
|
|
159
160
|
import "dotenv/config";
|
|
160
161
|
|
|
161
162
|
// src/ui/App.tsx
|
|
162
|
-
import { useEffect as useEffect9, useMemo as useMemo2, useState as
|
|
163
|
-
import { Box as
|
|
163
|
+
import { useEffect as useEffect9, useMemo as useMemo2, useState as useState14 } from "react";
|
|
164
|
+
import { Box as Box18, Text as Text19, useApp as useApp2, useStdout as useStdout2, useInput as useInput14 } from "ink";
|
|
164
165
|
import TextInput6 from "ink-text-input";
|
|
165
166
|
|
|
166
167
|
// src/config.ts
|
|
@@ -406,10 +407,10 @@ async function openGitHubAuthorizationPage() {
|
|
|
406
407
|
}
|
|
407
408
|
|
|
408
409
|
// src/ui/RepoList.tsx
|
|
409
|
-
import
|
|
410
|
-
import { Box as
|
|
410
|
+
import React12, { useEffect as useEffect8, useMemo, useState as useState12, useRef, useCallback } from "react";
|
|
411
|
+
import { Box as Box15, Text as Text16, useApp, useInput as useInput12, useStdout } from "ink";
|
|
411
412
|
import TextInput5 from "ink-text-input";
|
|
412
|
-
import
|
|
413
|
+
import chalk12 from "chalk";
|
|
413
414
|
|
|
414
415
|
// src/apolloMeta.ts
|
|
415
416
|
import fs2 from "fs";
|
|
@@ -638,6 +639,51 @@ function formatDate(dateStr) {
|
|
|
638
639
|
if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
|
|
639
640
|
return `${Math.floor(diffDays / 365)} years ago`;
|
|
640
641
|
}
|
|
642
|
+
async function copyToClipboard(text) {
|
|
643
|
+
try {
|
|
644
|
+
const clipboardy = await import("clipboardy");
|
|
645
|
+
await clipboardy.write(text);
|
|
646
|
+
return;
|
|
647
|
+
} catch (error) {
|
|
648
|
+
const { spawn } = await import("child_process");
|
|
649
|
+
const { promisify } = await import("util");
|
|
650
|
+
const spawnCommand = (command, args = []) => {
|
|
651
|
+
return new Promise((resolve, reject) => {
|
|
652
|
+
const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
653
|
+
child.stdin.write(text);
|
|
654
|
+
child.stdin.end();
|
|
655
|
+
child.on("close", (code) => {
|
|
656
|
+
if (code === 0) {
|
|
657
|
+
resolve();
|
|
658
|
+
} else {
|
|
659
|
+
reject(new Error(`Command failed with code ${code}`));
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
child.on("error", reject);
|
|
663
|
+
});
|
|
664
|
+
};
|
|
665
|
+
try {
|
|
666
|
+
const platform = process.platform;
|
|
667
|
+
if (platform === "darwin") {
|
|
668
|
+
await spawnCommand("pbcopy");
|
|
669
|
+
} else if (platform === "win32") {
|
|
670
|
+
await spawnCommand("clip");
|
|
671
|
+
} else {
|
|
672
|
+
try {
|
|
673
|
+
await spawnCommand("xclip", ["-selection", "clipboard"]);
|
|
674
|
+
} catch {
|
|
675
|
+
try {
|
|
676
|
+
await spawnCommand("xsel", ["--clipboard", "--input"]);
|
|
677
|
+
} catch {
|
|
678
|
+
await spawnCommand("wl-copy");
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
} catch (osError) {
|
|
683
|
+
throw new Error(`Failed to copy to clipboard. Please install a clipboard utility for your system.`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
641
687
|
|
|
642
688
|
// src/ui/components/modals/InfoModal.tsx
|
|
643
689
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -1193,10 +1239,136 @@ function RenameModal({ repo, onRename, onCancel }) {
|
|
|
1193
1239
|
);
|
|
1194
1240
|
}
|
|
1195
1241
|
|
|
1196
|
-
// src/ui/components/
|
|
1197
|
-
import {
|
|
1242
|
+
// src/ui/components/modals/CopyUrlModal.tsx
|
|
1243
|
+
import { useState as useState11 } from "react";
|
|
1244
|
+
import { Box as Box11, Text as Text12, useInput as useInput11 } from "ink";
|
|
1198
1245
|
import chalk10 from "chalk";
|
|
1199
|
-
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1246
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1247
|
+
function CopyUrlModal({ repo, terminalWidth, onClose, onCopy }) {
|
|
1248
|
+
const [copyError, setCopyError] = useState11(null);
|
|
1249
|
+
const [selectedType, setSelectedType] = useState11("SSH");
|
|
1250
|
+
const urlTypes = ["SSH", "HTTPS"];
|
|
1251
|
+
useInput11((input, key) => {
|
|
1252
|
+
if (!repo) return;
|
|
1253
|
+
const ch = input?.toLowerCase();
|
|
1254
|
+
if (key.escape || ch === "c" || ch === "q") {
|
|
1255
|
+
onClose();
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
if (key.leftArrow || key.rightArrow) {
|
|
1259
|
+
const currentIndex = urlTypes.indexOf(selectedType);
|
|
1260
|
+
let newIndex;
|
|
1261
|
+
if (key.leftArrow) {
|
|
1262
|
+
newIndex = currentIndex === 0 ? urlTypes.length - 1 : currentIndex - 1;
|
|
1263
|
+
} else {
|
|
1264
|
+
newIndex = currentIndex === urlTypes.length - 1 ? 0 : currentIndex + 1;
|
|
1265
|
+
}
|
|
1266
|
+
setSelectedType(urlTypes[newIndex]);
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
if (key.upArrow) {
|
|
1270
|
+
setSelectedType("SSH");
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
if (key.downArrow) {
|
|
1274
|
+
setSelectedType("HTTPS");
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
if (key.return || ch === "y") {
|
|
1278
|
+
const sshUrl2 = `git@github.com:${repo.nameWithOwner}.git`;
|
|
1279
|
+
const httpsUrl2 = `https://github.com/${repo.nameWithOwner}.git`;
|
|
1280
|
+
const urlToCopy = selectedType === "SSH" ? sshUrl2 : httpsUrl2;
|
|
1281
|
+
handleCopy(urlToCopy, selectedType);
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
if (ch === "s") {
|
|
1285
|
+
const sshUrl2 = `git@github.com:${repo.nameWithOwner}.git`;
|
|
1286
|
+
handleCopy(sshUrl2, "SSH");
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
if (ch === "h") {
|
|
1290
|
+
const httpsUrl2 = `https://github.com/${repo.nameWithOwner}.git`;
|
|
1291
|
+
handleCopy(httpsUrl2, "HTTPS");
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
if (!repo) {
|
|
1296
|
+
return /* @__PURE__ */ jsx12(Text12, { color: "red", children: "No repository selected." });
|
|
1297
|
+
}
|
|
1298
|
+
const sshUrl = `git@github.com:${repo.nameWithOwner}.git`;
|
|
1299
|
+
const httpsUrl = `https://github.com/${repo.nameWithOwner}.git`;
|
|
1300
|
+
const handleCopy = async (url, type) => {
|
|
1301
|
+
try {
|
|
1302
|
+
setCopyError(null);
|
|
1303
|
+
await onCopy(url, type);
|
|
1304
|
+
onClose();
|
|
1305
|
+
} catch (error) {
|
|
1306
|
+
const message = error instanceof Error ? error.message : String(error) || "Unknown error";
|
|
1307
|
+
setCopyError(`Failed to copy ${type} URL: ${message}`);
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
return /* @__PURE__ */ jsxs11(
|
|
1311
|
+
Box11,
|
|
1312
|
+
{
|
|
1313
|
+
flexDirection: "column",
|
|
1314
|
+
borderStyle: "round",
|
|
1315
|
+
borderColor: "blue",
|
|
1316
|
+
paddingX: 3,
|
|
1317
|
+
paddingY: 2,
|
|
1318
|
+
width: Math.min(terminalWidth - 8, 80),
|
|
1319
|
+
children: [
|
|
1320
|
+
/* @__PURE__ */ jsx12(Text12, { bold: true, color: "blue", children: "Copy Repository URL" }),
|
|
1321
|
+
/* @__PURE__ */ jsx12(Box11, { height: 1, children: /* @__PURE__ */ jsx12(Text12, { children: " " }) }),
|
|
1322
|
+
/* @__PURE__ */ jsx12(Text12, { children: chalk10.bold(repo.nameWithOwner) }),
|
|
1323
|
+
/* @__PURE__ */ jsx12(Box11, { height: 1, children: /* @__PURE__ */ jsx12(Text12, { children: " " }) }),
|
|
1324
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "SSH URL:" }),
|
|
1325
|
+
/* @__PURE__ */ jsx12(
|
|
1326
|
+
Box11,
|
|
1327
|
+
{
|
|
1328
|
+
paddingX: 2,
|
|
1329
|
+
paddingY: 1,
|
|
1330
|
+
borderStyle: "single",
|
|
1331
|
+
borderColor: selectedType === "SSH" ? "blue" : "gray",
|
|
1332
|
+
children: /* @__PURE__ */ jsxs11(Text12, { color: selectedType === "SSH" ? "blue" : void 0, children: [
|
|
1333
|
+
selectedType === "SSH" ? "\u25B6 " : " ",
|
|
1334
|
+
sshUrl
|
|
1335
|
+
] })
|
|
1336
|
+
}
|
|
1337
|
+
),
|
|
1338
|
+
/* @__PURE__ */ jsx12(Box11, { height: 1, children: /* @__PURE__ */ jsx12(Text12, { children: " " }) }),
|
|
1339
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "HTTPS URL:" }),
|
|
1340
|
+
/* @__PURE__ */ jsx12(
|
|
1341
|
+
Box11,
|
|
1342
|
+
{
|
|
1343
|
+
paddingX: 2,
|
|
1344
|
+
paddingY: 1,
|
|
1345
|
+
borderStyle: "single",
|
|
1346
|
+
borderColor: selectedType === "HTTPS" ? "blue" : "gray",
|
|
1347
|
+
children: /* @__PURE__ */ jsxs11(Text12, { color: selectedType === "HTTPS" ? "blue" : void 0, children: [
|
|
1348
|
+
selectedType === "HTTPS" ? "\u25B6 " : " ",
|
|
1349
|
+
httpsUrl
|
|
1350
|
+
] })
|
|
1351
|
+
}
|
|
1352
|
+
),
|
|
1353
|
+
/* @__PURE__ */ jsx12(Box11, { height: 1, children: /* @__PURE__ */ jsx12(Text12, { children: " " }) }),
|
|
1354
|
+
/* @__PURE__ */ jsxs11(Text12, { color: "gray", children: [
|
|
1355
|
+
"\u2191\u2193 Select \u2022 Enter/Y to copy ",
|
|
1356
|
+
selectedType,
|
|
1357
|
+
" \u2022 S copy SSH \u2022 H copy HTTPS \u2022 Esc/Q/C to close"
|
|
1358
|
+
] }),
|
|
1359
|
+
copyError && /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1360
|
+
/* @__PURE__ */ jsx12(Box11, { height: 1, children: /* @__PURE__ */ jsx12(Text12, { children: " " }) }),
|
|
1361
|
+
/* @__PURE__ */ jsx12(Text12, { color: "red", children: copyError })
|
|
1362
|
+
] })
|
|
1363
|
+
]
|
|
1364
|
+
}
|
|
1365
|
+
);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// src/ui/components/repo/RepoRow.tsx
|
|
1369
|
+
import { Box as Box12, Text as Text13 } from "ink";
|
|
1370
|
+
import chalk11 from "chalk";
|
|
1371
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1200
1372
|
function RepoRow({
|
|
1201
1373
|
repo,
|
|
1202
1374
|
selected,
|
|
@@ -1212,50 +1384,50 @@ function RepoRow({
|
|
|
1212
1384
|
const commitsBehind = hasCommitData ? repo.parent.defaultBranchRef.target.history.totalCount - repo.defaultBranchRef.target.history.totalCount : 0;
|
|
1213
1385
|
const showCommitsBehind = forkTracking && hasCommitData;
|
|
1214
1386
|
let line1 = "";
|
|
1215
|
-
const numColor = selected ?
|
|
1216
|
-
const nameColor = selected ?
|
|
1387
|
+
const numColor = selected ? chalk11.cyan : chalk11.gray;
|
|
1388
|
+
const nameColor = selected ? chalk11.cyan.bold : chalk11.white;
|
|
1217
1389
|
line1 += numColor(`${String(index).padStart(3, " ")}.`);
|
|
1218
1390
|
line1 += nameColor(` ${repo.nameWithOwner}`);
|
|
1219
1391
|
if (repo.visibility === "INTERNAL") {
|
|
1220
|
-
line1 +=
|
|
1392
|
+
line1 += chalk11.magenta(" Internal");
|
|
1221
1393
|
} else if (repo.visibility === "PRIVATE" || repo.isPrivate && !repo.visibility) {
|
|
1222
|
-
line1 +=
|
|
1394
|
+
line1 += chalk11.yellow(" Private");
|
|
1223
1395
|
}
|
|
1224
|
-
if (repo.isArchived) line1 += " " +
|
|
1396
|
+
if (repo.isArchived) line1 += " " + chalk11.bgGray.whiteBright(" Archived ") + " ";
|
|
1225
1397
|
if (repo.isFork && repo.parent) {
|
|
1226
|
-
line1 +=
|
|
1398
|
+
line1 += chalk11.blue(` Fork of ${repo.parent.nameWithOwner}`);
|
|
1227
1399
|
if (showCommitsBehind) {
|
|
1228
1400
|
if (commitsBehind > 0) {
|
|
1229
|
-
line1 +=
|
|
1401
|
+
line1 += chalk11.yellow(` (${commitsBehind} behind)`);
|
|
1230
1402
|
} else {
|
|
1231
|
-
line1 +=
|
|
1403
|
+
line1 += chalk11.green(` (0 behind)`);
|
|
1232
1404
|
}
|
|
1233
1405
|
}
|
|
1234
1406
|
}
|
|
1235
1407
|
let line2 = " ";
|
|
1236
|
-
const metaColor = selected ?
|
|
1237
|
-
if (langName) line2 +=
|
|
1408
|
+
const metaColor = selected ? chalk11.white : chalk11.gray;
|
|
1409
|
+
if (langName) line2 += chalk11.hex(langColor)("\u25CF ") + metaColor(`${langName} `);
|
|
1238
1410
|
line2 += metaColor(`\u2605 ${repo.stargazerCount} \u2442 ${repo.forkCount} Updated ${formatDate(repo.updatedAt)}`);
|
|
1239
1411
|
const line3 = repo.description ? ` ${truncate(repo.description, Math.max(30, maxWidth - 10))}` : null;
|
|
1240
1412
|
let fullText = line1 + "\n" + line2;
|
|
1241
1413
|
if (line3) fullText += "\n" + metaColor(line3);
|
|
1242
1414
|
const spacingAbove = Math.floor(spacingLines / 2);
|
|
1243
1415
|
const spacingBelow = spacingLines - spacingAbove;
|
|
1244
|
-
return /* @__PURE__ */
|
|
1245
|
-
spacingAbove > 0 && /* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1247
|
-
spacingBelow > 0 && /* @__PURE__ */
|
|
1416
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", backgroundColor: selected ? "gray" : void 0, children: [
|
|
1417
|
+
spacingAbove > 0 && /* @__PURE__ */ jsx13(Box12, { height: spacingAbove, children: /* @__PURE__ */ jsx13(Text13, { children: " " }) }),
|
|
1418
|
+
/* @__PURE__ */ jsx13(Text13, { children: dim ? chalk11.dim(fullText) : fullText }),
|
|
1419
|
+
spacingBelow > 0 && /* @__PURE__ */ jsx13(Box12, { height: spacingBelow, children: /* @__PURE__ */ jsx13(Text13, { children: " " }) })
|
|
1248
1420
|
] });
|
|
1249
1421
|
}
|
|
1250
1422
|
|
|
1251
1423
|
// src/ui/components/repo/FilterInput.tsx
|
|
1252
|
-
import { Box as
|
|
1424
|
+
import { Box as Box13, Text as Text14 } from "ink";
|
|
1253
1425
|
import TextInput4 from "ink-text-input";
|
|
1254
|
-
import { jsx as
|
|
1426
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1255
1427
|
|
|
1256
1428
|
// src/ui/components/repo/RepoListHeader.tsx
|
|
1257
|
-
import { Box as
|
|
1258
|
-
import { Fragment as
|
|
1429
|
+
import { Box as Box14, Text as Text15 } from "ink";
|
|
1430
|
+
import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1259
1431
|
function RepoListHeader({
|
|
1260
1432
|
ownerContext,
|
|
1261
1433
|
sortKey,
|
|
@@ -1269,35 +1441,35 @@ function RepoListHeader({
|
|
|
1269
1441
|
}) {
|
|
1270
1442
|
const contextLabel = ownerContext === "personal" ? "Personal Account" : ownerContext?.type === "organization" ? `Organization: ${ownerContext.name ?? ownerContext.login}` : "";
|
|
1271
1443
|
const visibilityLabel = visibilityFilter === "public" ? "Public" : visibilityFilter === "private" ? isEnterprise ? "Private/Internal" : "Private" : visibilityFilter === "internal" ? "Internal" : "";
|
|
1272
|
-
return /* @__PURE__ */
|
|
1273
|
-
contextLabel && /* @__PURE__ */
|
|
1274
|
-
/* @__PURE__ */
|
|
1444
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", gap: 2, marginBottom: 1, children: [
|
|
1445
|
+
contextLabel && /* @__PURE__ */ jsx15(Text15, { children: contextLabel }),
|
|
1446
|
+
/* @__PURE__ */ jsxs14(Text15, { color: "gray", dimColor: true, children: [
|
|
1275
1447
|
"Sort: ",
|
|
1276
1448
|
sortKey,
|
|
1277
1449
|
" ",
|
|
1278
1450
|
sortDir === "asc" ? "\u2191" : "\u2193"
|
|
1279
1451
|
] }),
|
|
1280
|
-
/* @__PURE__ */
|
|
1452
|
+
/* @__PURE__ */ jsxs14(Text15, { color: "gray", dimColor: true, children: [
|
|
1281
1453
|
"Fork Status - Commits Behind: ",
|
|
1282
1454
|
forkTracking ? "ON" : "OFF"
|
|
1283
1455
|
] }),
|
|
1284
|
-
!!visibilityLabel && /* @__PURE__ */
|
|
1456
|
+
!!visibilityLabel && /* @__PURE__ */ jsxs14(Text15, { color: "yellow", children: [
|
|
1285
1457
|
"Visibility: ",
|
|
1286
1458
|
visibilityLabel
|
|
1287
1459
|
] }),
|
|
1288
|
-
filter && !searchActive && /* @__PURE__ */
|
|
1460
|
+
filter && !searchActive && /* @__PURE__ */ jsxs14(Text15, { color: "cyan", children: [
|
|
1289
1461
|
'Filter: "',
|
|
1290
1462
|
filter,
|
|
1291
1463
|
'"'
|
|
1292
1464
|
] }),
|
|
1293
|
-
searchActive && /* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1465
|
+
searchActive && /* @__PURE__ */ jsxs14(Fragment7, { children: [
|
|
1466
|
+
/* @__PURE__ */ jsxs14(Text15, { color: "cyan", children: [
|
|
1295
1467
|
'Search: "',
|
|
1296
1468
|
filter.trim(),
|
|
1297
1469
|
'"'
|
|
1298
1470
|
] }),
|
|
1299
|
-
searchLoading && /* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
1471
|
+
searchLoading && /* @__PURE__ */ jsx15(Box14, { marginLeft: 1, children: /* @__PURE__ */ jsxs14(Text15, { color: "cyan", children: [
|
|
1472
|
+
/* @__PURE__ */ jsx15(SlowSpinner, {}),
|
|
1301
1473
|
" Searching\u2026"
|
|
1302
1474
|
] }) })
|
|
1303
1475
|
] })
|
|
@@ -1305,7 +1477,7 @@ function RepoListHeader({
|
|
|
1305
1477
|
}
|
|
1306
1478
|
|
|
1307
1479
|
// src/ui/RepoList.tsx
|
|
1308
|
-
import { Fragment as
|
|
1480
|
+
import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1309
1481
|
var getPageSize = () => {
|
|
1310
1482
|
const envValue = process.env.REPOS_PER_FETCH;
|
|
1311
1483
|
if (envValue) {
|
|
@@ -1321,7 +1493,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1321
1493
|
const { exit } = useApp();
|
|
1322
1494
|
const { stdout } = useStdout();
|
|
1323
1495
|
const client = useMemo(() => makeClient(token), [token]);
|
|
1324
|
-
const [debugMessages, setDebugMessages] =
|
|
1496
|
+
const [debugMessages, setDebugMessages] = useState12([]);
|
|
1325
1497
|
const addDebugMessage = useCallback((msg) => {
|
|
1326
1498
|
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
1327
1499
|
setDebugMessages((prev) => [...prev.slice(-9), msg]);
|
|
@@ -1331,7 +1503,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1331
1503
|
useEffect8(() => {
|
|
1332
1504
|
handleOrgContextChangeRef.current = onOrgContextChange;
|
|
1333
1505
|
}, [onOrgContextChange]);
|
|
1334
|
-
|
|
1506
|
+
React12.useEffect(() => {
|
|
1335
1507
|
addDebugMessage(`[RepoList] Component mounted`);
|
|
1336
1508
|
logger.info("RepoList component mounted", {
|
|
1337
1509
|
token: token ? "present" : "missing",
|
|
@@ -1343,62 +1515,74 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1343
1515
|
}, []);
|
|
1344
1516
|
const terminalWidth = stdout?.columns ?? 80;
|
|
1345
1517
|
const availableHeight = maxVisibleRows ?? 20;
|
|
1346
|
-
const [items, setItems] =
|
|
1347
|
-
const [cursor, setCursor] =
|
|
1348
|
-
const [endCursor, setEndCursor] =
|
|
1349
|
-
const [hasNextPage, setHasNextPage] =
|
|
1350
|
-
const [totalCount, setTotalCount] =
|
|
1351
|
-
const [loading, setLoading] =
|
|
1352
|
-
const [sortingLoading, setSortingLoading] =
|
|
1353
|
-
const [refreshing, setRefreshing] =
|
|
1354
|
-
const [loadingMore, setLoadingMore] =
|
|
1355
|
-
const [error, setError] =
|
|
1356
|
-
const [rateLimit, setRateLimit] =
|
|
1357
|
-
const [prevRateLimit, setPrevRateLimit] =
|
|
1358
|
-
const [density, setDensity] =
|
|
1359
|
-
const [prefsLoaded, setPrefsLoaded] =
|
|
1360
|
-
const [ownerContext, setOwnerContext] =
|
|
1361
|
-
const [ownerAffiliations, setOwnerAffiliations] =
|
|
1362
|
-
const [orgSwitcherOpen, setOrgSwitcherOpen] =
|
|
1363
|
-
const [searchItems, setSearchItems] =
|
|
1364
|
-
const [searchEndCursor, setSearchEndCursor] =
|
|
1365
|
-
const [searchHasNextPage, setSearchHasNextPage] =
|
|
1366
|
-
const [searchTotalCount, setSearchTotalCount] =
|
|
1367
|
-
const [searchLoading, setSearchLoading] =
|
|
1368
|
-
const [deleteMode, setDeleteMode] =
|
|
1369
|
-
const [deleteTarget, setDeleteTarget] =
|
|
1370
|
-
const [deleteCode, setDeleteCode] =
|
|
1371
|
-
const [typedCode, setTypedCode] =
|
|
1372
|
-
const [deleting, setDeleting] =
|
|
1373
|
-
const [deleteError, setDeleteError] =
|
|
1374
|
-
const [deleteConfirmStage, setDeleteConfirmStage] =
|
|
1375
|
-
const [confirmFocus, setConfirmFocus] =
|
|
1376
|
-
const [archiveMode, setArchiveMode] =
|
|
1377
|
-
const [archiveTarget, setArchiveTarget] =
|
|
1378
|
-
const [archiving, setArchiving] =
|
|
1379
|
-
const [archiveError, setArchiveError] =
|
|
1380
|
-
const [archiveFocus, setArchiveFocus] =
|
|
1381
|
-
const [renameMode, setRenameMode] =
|
|
1382
|
-
const [renameTarget, setRenameTarget] =
|
|
1383
|
-
const [syncMode, setSyncMode] =
|
|
1384
|
-
const [syncTarget, setSyncTarget] =
|
|
1385
|
-
const [syncing, setSyncing] =
|
|
1386
|
-
const [syncError, setSyncError] =
|
|
1387
|
-
const [syncFocus, setSyncFocus] =
|
|
1388
|
-
const [syncTrigger, setSyncTrigger] =
|
|
1389
|
-
const [infoMode, setInfoMode] =
|
|
1390
|
-
const [infoRepo, setInfoRepo] =
|
|
1391
|
-
const [logoutMode, setLogoutMode] =
|
|
1392
|
-
const [logoutFocus, setLogoutFocus] =
|
|
1393
|
-
const [logoutError, setLogoutError] =
|
|
1394
|
-
const [visibilityMode, setVisibilityMode] =
|
|
1395
|
-
const [isEnterpriseOrg, setIsEnterpriseOrg] =
|
|
1396
|
-
const [hasInternalRepos, setHasInternalRepos] =
|
|
1397
|
-
const [changeVisibilityMode, setChangeVisibilityMode] =
|
|
1398
|
-
const [changeVisibilityTarget, setChangeVisibilityTarget] =
|
|
1399
|
-
const [changingVisibility, setChangingVisibility] =
|
|
1400
|
-
const [changeVisibilityError, setChangeVisibilityError] =
|
|
1401
|
-
const [sortMode, setSortMode] =
|
|
1518
|
+
const [items, setItems] = useState12([]);
|
|
1519
|
+
const [cursor, setCursor] = useState12(0);
|
|
1520
|
+
const [endCursor, setEndCursor] = useState12(null);
|
|
1521
|
+
const [hasNextPage, setHasNextPage] = useState12(false);
|
|
1522
|
+
const [totalCount, setTotalCount] = useState12(0);
|
|
1523
|
+
const [loading, setLoading] = useState12(true);
|
|
1524
|
+
const [sortingLoading, setSortingLoading] = useState12(false);
|
|
1525
|
+
const [refreshing, setRefreshing] = useState12(false);
|
|
1526
|
+
const [loadingMore, setLoadingMore] = useState12(false);
|
|
1527
|
+
const [error, setError] = useState12(null);
|
|
1528
|
+
const [rateLimit, setRateLimit] = useState12(void 0);
|
|
1529
|
+
const [prevRateLimit, setPrevRateLimit] = useState12(void 0);
|
|
1530
|
+
const [density, setDensity] = useState12(2);
|
|
1531
|
+
const [prefsLoaded, setPrefsLoaded] = useState12(false);
|
|
1532
|
+
const [ownerContext, setOwnerContext] = useState12("personal");
|
|
1533
|
+
const [ownerAffiliations, setOwnerAffiliations] = useState12(["OWNER"]);
|
|
1534
|
+
const [orgSwitcherOpen, setOrgSwitcherOpen] = useState12(false);
|
|
1535
|
+
const [searchItems, setSearchItems] = useState12([]);
|
|
1536
|
+
const [searchEndCursor, setSearchEndCursor] = useState12(null);
|
|
1537
|
+
const [searchHasNextPage, setSearchHasNextPage] = useState12(false);
|
|
1538
|
+
const [searchTotalCount, setSearchTotalCount] = useState12(0);
|
|
1539
|
+
const [searchLoading, setSearchLoading] = useState12(false);
|
|
1540
|
+
const [deleteMode, setDeleteMode] = useState12(false);
|
|
1541
|
+
const [deleteTarget, setDeleteTarget] = useState12(null);
|
|
1542
|
+
const [deleteCode, setDeleteCode] = useState12("");
|
|
1543
|
+
const [typedCode, setTypedCode] = useState12("");
|
|
1544
|
+
const [deleting, setDeleting] = useState12(false);
|
|
1545
|
+
const [deleteError, setDeleteError] = useState12(null);
|
|
1546
|
+
const [deleteConfirmStage, setDeleteConfirmStage] = useState12(false);
|
|
1547
|
+
const [confirmFocus, setConfirmFocus] = useState12("delete");
|
|
1548
|
+
const [archiveMode, setArchiveMode] = useState12(false);
|
|
1549
|
+
const [archiveTarget, setArchiveTarget] = useState12(null);
|
|
1550
|
+
const [archiving, setArchiving] = useState12(false);
|
|
1551
|
+
const [archiveError, setArchiveError] = useState12(null);
|
|
1552
|
+
const [archiveFocus, setArchiveFocus] = useState12("confirm");
|
|
1553
|
+
const [renameMode, setRenameMode] = useState12(false);
|
|
1554
|
+
const [renameTarget, setRenameTarget] = useState12(null);
|
|
1555
|
+
const [syncMode, setSyncMode] = useState12(false);
|
|
1556
|
+
const [syncTarget, setSyncTarget] = useState12(null);
|
|
1557
|
+
const [syncing, setSyncing] = useState12(false);
|
|
1558
|
+
const [syncError, setSyncError] = useState12(null);
|
|
1559
|
+
const [syncFocus, setSyncFocus] = useState12("confirm");
|
|
1560
|
+
const [syncTrigger, setSyncTrigger] = useState12(false);
|
|
1561
|
+
const [infoMode, setInfoMode] = useState12(false);
|
|
1562
|
+
const [infoRepo, setInfoRepo] = useState12(null);
|
|
1563
|
+
const [logoutMode, setLogoutMode] = useState12(false);
|
|
1564
|
+
const [logoutFocus, setLogoutFocus] = useState12("confirm");
|
|
1565
|
+
const [logoutError, setLogoutError] = useState12(null);
|
|
1566
|
+
const [visibilityMode, setVisibilityMode] = useState12(false);
|
|
1567
|
+
const [isEnterpriseOrg, setIsEnterpriseOrg] = useState12(false);
|
|
1568
|
+
const [hasInternalRepos, setHasInternalRepos] = useState12(false);
|
|
1569
|
+
const [changeVisibilityMode, setChangeVisibilityMode] = useState12(false);
|
|
1570
|
+
const [changeVisibilityTarget, setChangeVisibilityTarget] = useState12(null);
|
|
1571
|
+
const [changingVisibility, setChangingVisibility] = useState12(false);
|
|
1572
|
+
const [changeVisibilityError, setChangeVisibilityError] = useState12(null);
|
|
1573
|
+
const [sortMode, setSortMode] = useState12(false);
|
|
1574
|
+
const [copyUrlMode, setCopyUrlMode] = useState12(false);
|
|
1575
|
+
const [copyUrlTarget, setCopyUrlTarget] = useState12(null);
|
|
1576
|
+
const [copyToast, setCopyToast] = useState12(null);
|
|
1577
|
+
const copyToastTimerRef = useRef(null);
|
|
1578
|
+
useEffect8(() => {
|
|
1579
|
+
return () => {
|
|
1580
|
+
if (copyToastTimerRef.current) {
|
|
1581
|
+
clearTimeout(copyToastTimerRef.current);
|
|
1582
|
+
copyToastTimerRef.current = null;
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
}, []);
|
|
1402
1586
|
const appliedInitialOrg = useRef(false);
|
|
1403
1587
|
useEffect8(() => {
|
|
1404
1588
|
(async () => {
|
|
@@ -1453,6 +1637,42 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1453
1637
|
setSyncFocus("confirm");
|
|
1454
1638
|
setSyncTrigger(false);
|
|
1455
1639
|
}
|
|
1640
|
+
function openCopyUrlModal(repo) {
|
|
1641
|
+
setCopyUrlMode(true);
|
|
1642
|
+
setCopyUrlTarget(repo);
|
|
1643
|
+
setCopyToast(null);
|
|
1644
|
+
}
|
|
1645
|
+
function closeCopyUrlModal() {
|
|
1646
|
+
setCopyUrlMode(false);
|
|
1647
|
+
setCopyUrlTarget(null);
|
|
1648
|
+
setCopyToast(null);
|
|
1649
|
+
}
|
|
1650
|
+
async function handleCopyUrl(url, type) {
|
|
1651
|
+
try {
|
|
1652
|
+
if (copyToastTimerRef.current) {
|
|
1653
|
+
clearTimeout(copyToastTimerRef.current);
|
|
1654
|
+
copyToastTimerRef.current = null;
|
|
1655
|
+
}
|
|
1656
|
+
await copyToClipboard(url);
|
|
1657
|
+
setCopyToast(`Copied ${type} URL to clipboard`);
|
|
1658
|
+
copyToastTimerRef.current = setTimeout(() => {
|
|
1659
|
+
setCopyToast(null);
|
|
1660
|
+
copyToastTimerRef.current = null;
|
|
1661
|
+
}, 3e3);
|
|
1662
|
+
} catch (error2) {
|
|
1663
|
+
if (copyToastTimerRef.current) {
|
|
1664
|
+
clearTimeout(copyToastTimerRef.current);
|
|
1665
|
+
copyToastTimerRef.current = null;
|
|
1666
|
+
}
|
|
1667
|
+
const message = error2 instanceof Error ? error2.message : String(error2) || "Unknown error";
|
|
1668
|
+
setCopyToast(`Failed to copy ${type} URL: ${message}`);
|
|
1669
|
+
copyToastTimerRef.current = setTimeout(() => {
|
|
1670
|
+
setCopyToast(null);
|
|
1671
|
+
copyToastTimerRef.current = null;
|
|
1672
|
+
}, 5e3);
|
|
1673
|
+
throw error2;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1456
1676
|
async function executeSync() {
|
|
1457
1677
|
if (!syncTarget || syncing) return;
|
|
1458
1678
|
try {
|
|
@@ -1622,12 +1842,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1622
1842
|
setDeleteError("Failed to delete repository. Ensure delete_repo scope and admin permissions.");
|
|
1623
1843
|
}
|
|
1624
1844
|
}
|
|
1625
|
-
const [filter, setFilter] =
|
|
1626
|
-
const [filterMode, setFilterMode] =
|
|
1627
|
-
const [sortKey, setSortKey] =
|
|
1628
|
-
const [sortDir, setSortDir] =
|
|
1629
|
-
const [forkTracking, setForkTracking] =
|
|
1630
|
-
const [visibilityFilter, setVisibilityFilter] =
|
|
1845
|
+
const [filter, setFilter] = useState12("");
|
|
1846
|
+
const [filterMode, setFilterMode] = useState12(false);
|
|
1847
|
+
const [sortKey, setSortKey] = useState12("updated");
|
|
1848
|
+
const [sortDir, setSortDir] = useState12("desc");
|
|
1849
|
+
const [forkTracking, setForkTracking] = useState12(true);
|
|
1850
|
+
const [visibilityFilter, setVisibilityFilter] = useState12("all");
|
|
1631
1851
|
const previousVisibilityFilter = useRef("all");
|
|
1632
1852
|
const sortFieldMap = {
|
|
1633
1853
|
"updated": "UPDATED_AT",
|
|
@@ -1908,7 +2128,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
1908
2128
|
fetchSearchPage(null, true, policy);
|
|
1909
2129
|
}
|
|
1910
2130
|
}, [viewerLogin]);
|
|
1911
|
-
|
|
2131
|
+
useInput12((input, key) => {
|
|
1912
2132
|
if (error) {
|
|
1913
2133
|
if (input && input.toUpperCase() === "Q") {
|
|
1914
2134
|
try {
|
|
@@ -2065,6 +2285,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2065
2285
|
if (sortMode) {
|
|
2066
2286
|
return;
|
|
2067
2287
|
}
|
|
2288
|
+
if (copyUrlMode) {
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2068
2291
|
if (filterMode) {
|
|
2069
2292
|
if (key.escape) {
|
|
2070
2293
|
setFilterMode(false);
|
|
@@ -2229,6 +2452,13 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2229
2452
|
setInfoMode(true);
|
|
2230
2453
|
return;
|
|
2231
2454
|
}
|
|
2455
|
+
if (input && input.toUpperCase() === "C") {
|
|
2456
|
+
const repo = visibleItems[cursor];
|
|
2457
|
+
if (repo) {
|
|
2458
|
+
openCopyUrlModal(repo);
|
|
2459
|
+
}
|
|
2460
|
+
return;
|
|
2461
|
+
}
|
|
2232
2462
|
if (input && input.toUpperCase() === "W") {
|
|
2233
2463
|
setOrgSwitcherOpen(true);
|
|
2234
2464
|
return;
|
|
@@ -2370,94 +2600,94 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2370
2600
|
exec(cmd);
|
|
2371
2601
|
}
|
|
2372
2602
|
const lowRate = rateLimit && rateLimit.remaining <= Math.ceil(rateLimit.limit * 0.1);
|
|
2373
|
-
const modalOpen = deleteMode || archiveMode || syncMode || logoutMode || infoMode || visibilityMode || renameMode;
|
|
2374
|
-
const headerBar = useMemo(() => /* @__PURE__ */
|
|
2375
|
-
/* @__PURE__ */
|
|
2376
|
-
/* @__PURE__ */
|
|
2603
|
+
const modalOpen = deleteMode || archiveMode || syncMode || logoutMode || infoMode || visibilityMode || renameMode || sortMode || changeVisibilityMode || copyUrlMode;
|
|
2604
|
+
const headerBar = useMemo(() => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: [
|
|
2605
|
+
/* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", gap: 1, children: [
|
|
2606
|
+
/* @__PURE__ */ jsxs15(Text16, { color: "cyan", bold: !modalOpen, dimColor: modalOpen, children: [
|
|
2377
2607
|
" ",
|
|
2378
2608
|
ownerContext === "personal" ? "Personal" : ownerContext.name || ownerContext.login,
|
|
2379
2609
|
ownerContext !== "personal" && isEnterpriseOrg && " (ENT)"
|
|
2380
2610
|
] }),
|
|
2381
|
-
/* @__PURE__ */
|
|
2382
|
-
/* @__PURE__ */
|
|
2611
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, color: modalOpen ? "gray" : void 0, dimColor: modalOpen ? true : void 0, children: "Repositories" }),
|
|
2612
|
+
/* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2383
2613
|
"(",
|
|
2384
2614
|
visibleItems.length,
|
|
2385
2615
|
"/",
|
|
2386
2616
|
searchActive ? searchTotalCount : totalCount,
|
|
2387
2617
|
")"
|
|
2388
2618
|
] }),
|
|
2389
|
-
(loading || searchLoading) && /* @__PURE__ */
|
|
2619
|
+
(loading || searchLoading) && /* @__PURE__ */ jsx16(Box15, { width: 2, flexShrink: 0, flexGrow: 0, marginLeft: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "yellow", children: /* @__PURE__ */ jsx16(SlowSpinner, {}) }) })
|
|
2390
2620
|
] }),
|
|
2391
|
-
rateLimit && /* @__PURE__ */
|
|
2621
|
+
rateLimit && /* @__PURE__ */ jsxs15(Text16, { color: lowRate ? "yellow" : "gray", children: [
|
|
2392
2622
|
"API: ",
|
|
2393
2623
|
rateLimit.remaining,
|
|
2394
2624
|
"/",
|
|
2395
2625
|
rateLimit.limit,
|
|
2396
|
-
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */
|
|
2626
|
+
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */ jsx16(Text16, { color: rateLimit.remaining < prevRateLimit ? "red" : "green", children: ` (${rateLimit.remaining - prevRateLimit > 0 ? "+" : ""}${rateLimit.remaining - prevRateLimit})` }),
|
|
2397
2627
|
" "
|
|
2398
2628
|
] })
|
|
2399
2629
|
] }), [visibleItems.length, searchActive, searchTotalCount, totalCount, loading, searchLoading, rateLimit, lowRate, modalOpen, prevRateLimit, ownerContext, isEnterpriseOrg]);
|
|
2400
2630
|
if (error) {
|
|
2401
|
-
return /* @__PURE__ */
|
|
2402
|
-
/* @__PURE__ */
|
|
2403
|
-
/* @__PURE__ */
|
|
2404
|
-
/* @__PURE__ */
|
|
2631
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: availableHeight, children: [
|
|
2632
|
+
/* @__PURE__ */ jsx16(Box15, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", gap: 1, children: [
|
|
2633
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: " Repositories" }),
|
|
2634
|
+
/* @__PURE__ */ jsx16(Text16, { color: "red", children: "(Error)" })
|
|
2405
2635
|
] }) }),
|
|
2406
|
-
/* @__PURE__ */
|
|
2407
|
-
/* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2636
|
+
/* @__PURE__ */ jsx16(Box15, { borderStyle: "single", borderColor: "red", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: /* @__PURE__ */ jsx16(Box15, { height: contentHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", alignItems: "center", children: [
|
|
2637
|
+
/* @__PURE__ */ jsx16(Text16, { color: "red", children: error }),
|
|
2638
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Press R to retry \u2022 Ctrl+L to logout \u2022 Q to quit" }) })
|
|
2409
2639
|
] }) }) }),
|
|
2410
|
-
/* @__PURE__ */
|
|
2640
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", children: "Press R to retry \u2022 Ctrl+L to logout \u2022 Q to quit" }) })
|
|
2411
2641
|
] });
|
|
2412
2642
|
}
|
|
2413
2643
|
if (loading && items.length === 0 || sortingLoading) {
|
|
2414
|
-
return /* @__PURE__ */
|
|
2415
|
-
/* @__PURE__ */
|
|
2416
|
-
/* @__PURE__ */
|
|
2417
|
-
/* @__PURE__ */
|
|
2644
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: availableHeight, children: [
|
|
2645
|
+
/* @__PURE__ */ jsx16(Box15, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", gap: 1, children: [
|
|
2646
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: " Repositories" }),
|
|
2647
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", children: "(Loading...)" })
|
|
2418
2648
|
] }) }),
|
|
2419
|
-
/* @__PURE__ */
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
/* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2649
|
+
/* @__PURE__ */ jsx16(Box15, { borderStyle: "single", borderColor: "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: /* @__PURE__ */ jsx16(Box15, { height: contentHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx16(Box15, { flexDirection: "column", alignItems: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", alignItems: "center", children: [
|
|
2650
|
+
/* @__PURE__ */ jsxs15(Box15, { height: 1, flexDirection: "row", children: [
|
|
2651
|
+
/* @__PURE__ */ jsx16(Box15, { width: 2, flexShrink: 0, flexGrow: 0, children: /* @__PURE__ */ jsx16(Text16, { color: "cyan", children: /* @__PURE__ */ jsx16(SlowSpinner, {}) }) }),
|
|
2652
|
+
/* @__PURE__ */ jsx16(Text16, { color: "cyan", children: refreshing ? "Refreshing..." : sortingLoading ? "Applying sort..." : "Loading repositories..." })
|
|
2423
2653
|
] }),
|
|
2424
|
-
/* @__PURE__ */
|
|
2654
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", children: refreshing ? "Fetching latest repository data" : sortingLoading ? `Sorting by ${sortKey} (${sortDir === "asc" ? "ascending" : "descending"})` : "Fetching your GitHub repositories" }) })
|
|
2425
2655
|
] }) }) }) }),
|
|
2426
|
-
/* @__PURE__ */
|
|
2656
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", children: "Please wait..." }) })
|
|
2427
2657
|
] });
|
|
2428
2658
|
}
|
|
2429
|
-
return /* @__PURE__ */
|
|
2659
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: availableHeight, children: [
|
|
2430
2660
|
headerBar,
|
|
2431
|
-
/* @__PURE__ */
|
|
2661
|
+
/* @__PURE__ */ jsx16(Box15, { borderStyle: "single", borderColor: modalOpen ? "gray" : "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: deleteMode && deleteTarget ? (
|
|
2432
2662
|
// Centered modal; hide list content while modal is open
|
|
2433
|
-
/* @__PURE__ */
|
|
2434
|
-
/* @__PURE__ */
|
|
2435
|
-
/* @__PURE__ */
|
|
2436
|
-
/* @__PURE__ */
|
|
2663
|
+
/* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
2664
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Delete Confirmation" }),
|
|
2665
|
+
/* @__PURE__ */ jsx16(Text16, { color: "red", children: "\u26A0\uFE0F Delete repository?" }),
|
|
2666
|
+
/* @__PURE__ */ jsx16(Box15, { height: 2, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2437
2667
|
(() => {
|
|
2438
2668
|
const langName = deleteTarget.primaryLanguage?.name || "";
|
|
2439
2669
|
const langColor = deleteTarget.primaryLanguage?.color || "#666666";
|
|
2440
2670
|
let line1 = "";
|
|
2441
|
-
line1 +=
|
|
2442
|
-
if (deleteTarget.isPrivate) line1 +=
|
|
2443
|
-
if (deleteTarget.isArchived) line1 +=
|
|
2444
|
-
if (deleteTarget.isFork && deleteTarget.parent) line1 +=
|
|
2671
|
+
line1 += chalk12.white(deleteTarget.nameWithOwner);
|
|
2672
|
+
if (deleteTarget.isPrivate) line1 += chalk12.yellow(" Private");
|
|
2673
|
+
if (deleteTarget.isArchived) line1 += chalk12.gray.dim(" Archived");
|
|
2674
|
+
if (deleteTarget.isFork && deleteTarget.parent) line1 += chalk12.blue(` Fork of ${deleteTarget.parent.nameWithOwner}`);
|
|
2445
2675
|
let line2 = "";
|
|
2446
|
-
if (langName) line2 +=
|
|
2447
|
-
line2 +=
|
|
2448
|
-
return /* @__PURE__ */
|
|
2449
|
-
/* @__PURE__ */
|
|
2450
|
-
/* @__PURE__ */
|
|
2676
|
+
if (langName) line2 += chalk12.hex(langColor)("\u25CF ") + chalk12.gray(`${langName} `);
|
|
2677
|
+
line2 += chalk12.gray(`\u2605 ${deleteTarget.stargazerCount} \u2442 ${deleteTarget.forkCount} Updated ${formatDate(deleteTarget.updatedAt)}`);
|
|
2678
|
+
return /* @__PURE__ */ jsxs15(Fragment8, { children: [
|
|
2679
|
+
/* @__PURE__ */ jsx16(Text16, { children: line1 }),
|
|
2680
|
+
/* @__PURE__ */ jsx16(Text16, { children: line2 })
|
|
2451
2681
|
] });
|
|
2452
2682
|
})(),
|
|
2453
|
-
/* @__PURE__ */
|
|
2683
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text16, { children: [
|
|
2454
2684
|
"Type ",
|
|
2455
|
-
/* @__PURE__ */
|
|
2685
|
+
/* @__PURE__ */ jsx16(Text16, { color: "yellow", bold: true, children: deleteCode }),
|
|
2456
2686
|
" to confirm."
|
|
2457
2687
|
] }) }),
|
|
2458
|
-
!deleteConfirmStage && /* @__PURE__ */
|
|
2459
|
-
/* @__PURE__ */
|
|
2460
|
-
/* @__PURE__ */
|
|
2688
|
+
!deleteConfirmStage && /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, children: [
|
|
2689
|
+
/* @__PURE__ */ jsx16(Text16, { children: "Confirm code: " }),
|
|
2690
|
+
/* @__PURE__ */ jsx16(
|
|
2461
2691
|
TextInput5,
|
|
2462
2692
|
{
|
|
2463
2693
|
value: typedCode,
|
|
@@ -2484,11 +2714,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2484
2714
|
}
|
|
2485
2715
|
)
|
|
2486
2716
|
] }),
|
|
2487
|
-
deleteConfirmStage && /* @__PURE__ */
|
|
2488
|
-
/* @__PURE__ */
|
|
2489
|
-
/* @__PURE__ */
|
|
2490
|
-
/* @__PURE__ */
|
|
2491
|
-
|
|
2717
|
+
deleteConfirmStage && /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
|
|
2718
|
+
/* @__PURE__ */ jsx16(Text16, { color: "red", children: "This action will permanently delete the repository. This cannot be undone." }),
|
|
2719
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
2720
|
+
/* @__PURE__ */ jsx16(
|
|
2721
|
+
Box15,
|
|
2492
2722
|
{
|
|
2493
2723
|
borderStyle: "round",
|
|
2494
2724
|
borderColor: "red",
|
|
@@ -2497,11 +2727,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2497
2727
|
alignItems: "center",
|
|
2498
2728
|
justifyContent: "center",
|
|
2499
2729
|
flexDirection: "column",
|
|
2500
|
-
children: /* @__PURE__ */
|
|
2730
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: confirmFocus === "delete" ? chalk12.bgRed.white.bold(" Delete ") : chalk12.red.bold("Delete") })
|
|
2501
2731
|
}
|
|
2502
2732
|
),
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
|
|
2733
|
+
/* @__PURE__ */ jsx16(
|
|
2734
|
+
Box15,
|
|
2505
2735
|
{
|
|
2506
2736
|
borderStyle: "round",
|
|
2507
2737
|
borderColor: confirmFocus === "cancel" ? "white" : "gray",
|
|
@@ -2510,16 +2740,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2510
2740
|
alignItems: "center",
|
|
2511
2741
|
justifyContent: "center",
|
|
2512
2742
|
flexDirection: "column",
|
|
2513
|
-
children: /* @__PURE__ */
|
|
2743
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: confirmFocus === "cancel" ? chalk12.bgGray.white.bold(" Cancel ") : chalk12.gray.bold("Cancel") })
|
|
2514
2744
|
}
|
|
2515
2745
|
)
|
|
2516
2746
|
] }),
|
|
2517
|
-
/* @__PURE__ */
|
|
2747
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2518
2748
|
"Press Enter to ",
|
|
2519
2749
|
confirmFocus === "delete" ? "Delete" : "Cancel",
|
|
2520
2750
|
" | Y to Delete | C to Cancel"
|
|
2521
2751
|
] }) }),
|
|
2522
|
-
/* @__PURE__ */
|
|
2752
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
2523
2753
|
TextInput5,
|
|
2524
2754
|
{
|
|
2525
2755
|
value: "",
|
|
@@ -2533,18 +2763,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2533
2763
|
}
|
|
2534
2764
|
) })
|
|
2535
2765
|
] }),
|
|
2536
|
-
deleteError && /* @__PURE__ */
|
|
2537
|
-
deleting && /* @__PURE__ */
|
|
2766
|
+
deleteError && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "magenta", children: deleteError }) }),
|
|
2767
|
+
deleting && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "yellow", children: "Deleting..." }) })
|
|
2538
2768
|
] }) })
|
|
2539
|
-
) : archiveMode && archiveTarget ? /* @__PURE__ */
|
|
2540
|
-
/* @__PURE__ */
|
|
2541
|
-
/* @__PURE__ */
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__PURE__ */
|
|
2546
|
-
/* @__PURE__ */
|
|
2547
|
-
|
|
2769
|
+
) : archiveMode && archiveTarget ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: archiveTarget.isArchived ? "green" : "yellow", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
2770
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: archiveTarget.isArchived ? "Unarchive Confirmation" : "Archive Confirmation" }),
|
|
2771
|
+
/* @__PURE__ */ jsx16(Text16, { color: archiveTarget.isArchived ? "green" : "yellow", children: archiveTarget.isArchived ? "\u21BA Unarchive repository?" : "\u26A0\uFE0F Archive repository?" }),
|
|
2772
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2773
|
+
/* @__PURE__ */ jsx16(Text16, { children: archiveTarget.nameWithOwner }),
|
|
2774
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { children: archiveTarget.isArchived ? "This will make the repository active again." : "This will make the repository read-only." }) }),
|
|
2775
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
2776
|
+
/* @__PURE__ */ jsx16(
|
|
2777
|
+
Box15,
|
|
2548
2778
|
{
|
|
2549
2779
|
borderStyle: "round",
|
|
2550
2780
|
borderColor: archiveTarget.isArchived ? "green" : "yellow",
|
|
@@ -2553,11 +2783,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2553
2783
|
alignItems: "center",
|
|
2554
2784
|
justifyContent: "center",
|
|
2555
2785
|
flexDirection: "column",
|
|
2556
|
-
children: /* @__PURE__ */
|
|
2786
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: archiveFocus === "confirm" ? chalk12.bgGreen.white.bold(` ${archiveTarget.isArchived ? "Unarchive" : "Archive"} `) : chalk12.bold[archiveTarget.isArchived ? "green" : "yellow"](archiveTarget.isArchived ? "Unarchive" : "Archive") })
|
|
2557
2787
|
}
|
|
2558
2788
|
),
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
|
|
2789
|
+
/* @__PURE__ */ jsx16(
|
|
2790
|
+
Box15,
|
|
2561
2791
|
{
|
|
2562
2792
|
borderStyle: "round",
|
|
2563
2793
|
borderColor: archiveFocus === "cancel" ? "white" : "gray",
|
|
@@ -2566,18 +2796,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2566
2796
|
alignItems: "center",
|
|
2567
2797
|
justifyContent: "center",
|
|
2568
2798
|
flexDirection: "column",
|
|
2569
|
-
children: /* @__PURE__ */
|
|
2799
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: archiveFocus === "cancel" ? chalk12.bgGray.white.bold(" Cancel ") : chalk12.gray.bold("Cancel") })
|
|
2570
2800
|
}
|
|
2571
2801
|
)
|
|
2572
2802
|
] }),
|
|
2573
|
-
/* @__PURE__ */
|
|
2803
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2574
2804
|
"Press Enter to ",
|
|
2575
2805
|
archiveFocus === "confirm" ? archiveTarget.isArchived ? "Unarchive" : "Archive" : "Cancel",
|
|
2576
2806
|
" | Y to ",
|
|
2577
2807
|
archiveTarget.isArchived ? "Unarchive" : "Archive",
|
|
2578
2808
|
" | C to Cancel"
|
|
2579
2809
|
] }) }),
|
|
2580
|
-
/* @__PURE__ */
|
|
2810
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
2581
2811
|
TextInput5,
|
|
2582
2812
|
{
|
|
2583
2813
|
value: "",
|
|
@@ -2592,28 +2822,28 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2592
2822
|
}
|
|
2593
2823
|
}
|
|
2594
2824
|
) }),
|
|
2595
|
-
archiveError && /* @__PURE__ */
|
|
2596
|
-
archiving && /* @__PURE__ */
|
|
2597
|
-
] }) }) : renameMode && renameTarget ? /* @__PURE__ */
|
|
2825
|
+
archiveError && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "magenta", children: archiveError }) }),
|
|
2826
|
+
archiving && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "yellow", children: archiveTarget.isArchived ? "Unarchiving..." : "Archiving..." }) })
|
|
2827
|
+
] }) }) : renameMode && renameTarget ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
2598
2828
|
RenameModal,
|
|
2599
2829
|
{
|
|
2600
2830
|
repo: renameTarget,
|
|
2601
2831
|
onRename: executeRename,
|
|
2602
2832
|
onCancel: closeRenameModal
|
|
2603
2833
|
}
|
|
2604
|
-
) }) : syncMode && syncTarget ? /* @__PURE__ */
|
|
2605
|
-
/* @__PURE__ */
|
|
2606
|
-
/* @__PURE__ */
|
|
2607
|
-
/* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
syncTarget.parent && /* @__PURE__ */
|
|
2834
|
+
) }) : syncMode && syncTarget ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
2835
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Sync Fork Confirmation" }),
|
|
2836
|
+
/* @__PURE__ */ jsx16(Text16, { color: "blue", children: "\u27F2 Sync fork with upstream?" }),
|
|
2837
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2838
|
+
/* @__PURE__ */ jsx16(Text16, { children: syncTarget.nameWithOwner }),
|
|
2839
|
+
syncTarget.parent && /* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2610
2840
|
"Upstream: ",
|
|
2611
2841
|
syncTarget.parent.nameWithOwner
|
|
2612
2842
|
] }),
|
|
2613
|
-
/* @__PURE__ */
|
|
2614
|
-
/* @__PURE__ */
|
|
2615
|
-
/* @__PURE__ */
|
|
2616
|
-
|
|
2843
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { children: "This will merge upstream changes into your fork." }) }),
|
|
2844
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
2845
|
+
/* @__PURE__ */ jsx16(
|
|
2846
|
+
Box15,
|
|
2617
2847
|
{
|
|
2618
2848
|
borderStyle: "round",
|
|
2619
2849
|
borderColor: "blue",
|
|
@@ -2622,11 +2852,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2622
2852
|
alignItems: "center",
|
|
2623
2853
|
justifyContent: "center",
|
|
2624
2854
|
flexDirection: "column",
|
|
2625
|
-
children: /* @__PURE__ */
|
|
2855
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: syncFocus === "confirm" ? chalk12.bgBlue.white.bold(" Sync ") : chalk12.blue.bold("Sync") })
|
|
2626
2856
|
}
|
|
2627
2857
|
),
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
|
|
2858
|
+
/* @__PURE__ */ jsx16(
|
|
2859
|
+
Box15,
|
|
2630
2860
|
{
|
|
2631
2861
|
borderStyle: "round",
|
|
2632
2862
|
borderColor: syncFocus === "cancel" ? "white" : "gray",
|
|
@@ -2635,16 +2865,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2635
2865
|
alignItems: "center",
|
|
2636
2866
|
justifyContent: "center",
|
|
2637
2867
|
flexDirection: "column",
|
|
2638
|
-
children: /* @__PURE__ */
|
|
2868
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: syncFocus === "cancel" ? chalk12.bgGray.white.bold(" Cancel ") : chalk12.gray.bold("Cancel") })
|
|
2639
2869
|
}
|
|
2640
2870
|
)
|
|
2641
2871
|
] }),
|
|
2642
|
-
/* @__PURE__ */
|
|
2872
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2643
2873
|
"Press Enter to ",
|
|
2644
2874
|
syncFocus === "confirm" ? "Sync" : "Cancel",
|
|
2645
2875
|
" | Y to Sync | C to Cancel"
|
|
2646
2876
|
] }) }),
|
|
2647
|
-
/* @__PURE__ */
|
|
2877
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
2648
2878
|
TextInput5,
|
|
2649
2879
|
{
|
|
2650
2880
|
value: "",
|
|
@@ -2659,14 +2889,14 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2659
2889
|
}
|
|
2660
2890
|
}
|
|
2661
2891
|
) }),
|
|
2662
|
-
syncError && /* @__PURE__ */
|
|
2663
|
-
syncing && /* @__PURE__ */
|
|
2664
|
-
] }) }) : logoutMode ? /* @__PURE__ */
|
|
2665
|
-
/* @__PURE__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2668
|
-
/* @__PURE__ */
|
|
2669
|
-
|
|
2892
|
+
syncError && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "magenta", children: syncError }) }),
|
|
2893
|
+
syncing && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "yellow", children: "Syncing..." }) })
|
|
2894
|
+
] }) }) : logoutMode ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
2895
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, children: "Logout Confirmation" }),
|
|
2896
|
+
/* @__PURE__ */ jsx16(Text16, { color: "cyan", children: "Are you sure you want to log out?" }),
|
|
2897
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
2898
|
+
/* @__PURE__ */ jsx16(
|
|
2899
|
+
Box15,
|
|
2670
2900
|
{
|
|
2671
2901
|
borderStyle: "round",
|
|
2672
2902
|
borderColor: "cyan",
|
|
@@ -2675,11 +2905,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2675
2905
|
alignItems: "center",
|
|
2676
2906
|
justifyContent: "center",
|
|
2677
2907
|
flexDirection: "column",
|
|
2678
|
-
children: /* @__PURE__ */
|
|
2908
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: logoutFocus === "confirm" ? chalk12.bgCyan.white.bold(" Logout ") : chalk12.cyan.bold("Logout") })
|
|
2679
2909
|
}
|
|
2680
2910
|
),
|
|
2681
|
-
/* @__PURE__ */
|
|
2682
|
-
|
|
2911
|
+
/* @__PURE__ */ jsx16(
|
|
2912
|
+
Box15,
|
|
2683
2913
|
{
|
|
2684
2914
|
borderStyle: "round",
|
|
2685
2915
|
borderColor: logoutFocus === "cancel" ? "white" : "gray",
|
|
@@ -2688,16 +2918,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2688
2918
|
alignItems: "center",
|
|
2689
2919
|
justifyContent: "center",
|
|
2690
2920
|
flexDirection: "column",
|
|
2691
|
-
children: /* @__PURE__ */
|
|
2921
|
+
children: /* @__PURE__ */ jsx16(Text16, { children: logoutFocus === "cancel" ? chalk12.bgGray.white.bold(" Cancel ") : chalk12.gray.bold("Cancel") })
|
|
2692
2922
|
}
|
|
2693
2923
|
)
|
|
2694
2924
|
] }),
|
|
2695
|
-
/* @__PURE__ */
|
|
2925
|
+
/* @__PURE__ */ jsx16(Box15, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2696
2926
|
"Press Enter to ",
|
|
2697
2927
|
logoutFocus === "confirm" ? "Logout" : "Cancel",
|
|
2698
2928
|
" | Y to Logout | C to Cancel"
|
|
2699
2929
|
] }) })
|
|
2700
|
-
] }) }) : orgSwitcherOpen ? /* @__PURE__ */
|
|
2930
|
+
] }) }) : orgSwitcherOpen ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
2701
2931
|
OrgSwitcher,
|
|
2702
2932
|
{
|
|
2703
2933
|
token,
|
|
@@ -2705,45 +2935,45 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2705
2935
|
onSelect: handleOrgContextChange,
|
|
2706
2936
|
onClose: () => setOrgSwitcherOpen(false)
|
|
2707
2937
|
}
|
|
2708
|
-
) }) : infoMode ? /* @__PURE__ */
|
|
2938
|
+
) }) : infoMode ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: (() => {
|
|
2709
2939
|
const repo = infoRepo || visibleItems[cursor];
|
|
2710
|
-
if (!repo) return /* @__PURE__ */
|
|
2940
|
+
if (!repo) return /* @__PURE__ */ jsx16(Text16, { color: "red", children: "No repository selected." });
|
|
2711
2941
|
const langName = repo.primaryLanguage?.name || "N/A";
|
|
2712
2942
|
const langColor = repo.primaryLanguage?.color || "#666666";
|
|
2713
|
-
return /* @__PURE__ */
|
|
2714
|
-
/* @__PURE__ */
|
|
2943
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 90), children: [
|
|
2944
|
+
/* @__PURE__ */ jsxs15(Text16, { bold: true, children: [
|
|
2715
2945
|
"Repository Info ",
|
|
2716
|
-
infoRepo ?
|
|
2946
|
+
infoRepo ? chalk12.dim("(cached)") : ""
|
|
2717
2947
|
] }),
|
|
2718
|
-
/* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
repo.description && /* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2722
|
-
/* @__PURE__ */
|
|
2723
|
-
repo.visibility === "PRIVATE" ?
|
|
2724
|
-
repo.isArchived ?
|
|
2725
|
-
repo.isFork ?
|
|
2948
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2949
|
+
/* @__PURE__ */ jsx16(Text16, { children: chalk12.bold(repo.nameWithOwner) }),
|
|
2950
|
+
repo.description && /* @__PURE__ */ jsx16(Text16, { color: "gray", children: repo.description }),
|
|
2951
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2952
|
+
/* @__PURE__ */ jsxs15(Text16, { children: [
|
|
2953
|
+
repo.visibility === "PRIVATE" ? chalk12.yellow("Private") : repo.visibility === "INTERNAL" ? chalk12.magenta("Internal") : chalk12.green("Public"),
|
|
2954
|
+
repo.isArchived ? chalk12.gray(" Archived") : "",
|
|
2955
|
+
repo.isFork ? chalk12.blue(" Fork") : ""
|
|
2726
2956
|
] }),
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
|
|
2730
|
-
|
|
2957
|
+
/* @__PURE__ */ jsx16(Text16, { children: chalk12.gray(`\u2605 ${repo.stargazerCount} \u2442 ${repo.forkCount}`) }),
|
|
2958
|
+
/* @__PURE__ */ jsxs15(Text16, { children: [
|
|
2959
|
+
chalk12.hex(langColor)(`\u25CF `),
|
|
2960
|
+
chalk12.gray(`${langName}`)
|
|
2731
2961
|
] }),
|
|
2732
|
-
/* @__PURE__ */
|
|
2962
|
+
/* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2733
2963
|
"Updated: ",
|
|
2734
2964
|
formatDate(repo.updatedAt),
|
|
2735
2965
|
" \u2022 Pushed: ",
|
|
2736
2966
|
formatDate(repo.pushedAt)
|
|
2737
2967
|
] }),
|
|
2738
|
-
/* @__PURE__ */
|
|
2968
|
+
/* @__PURE__ */ jsxs15(Text16, { color: "gray", children: [
|
|
2739
2969
|
"Size: ",
|
|
2740
2970
|
repo.diskUsage,
|
|
2741
2971
|
" KB"
|
|
2742
2972
|
] }),
|
|
2743
|
-
/* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
2973
|
+
/* @__PURE__ */ jsx16(Box15, { height: 1, children: /* @__PURE__ */ jsx16(Text16, { children: " " }) }),
|
|
2974
|
+
/* @__PURE__ */ jsx16(Text16, { color: "gray", children: "Press Esc or I to close" })
|
|
2745
2975
|
] });
|
|
2746
|
-
})() }) : visibilityMode ? /* @__PURE__ */
|
|
2976
|
+
})() }) : visibilityMode ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
2747
2977
|
VisibilityModal,
|
|
2748
2978
|
{
|
|
2749
2979
|
currentFilter: visibilityFilter,
|
|
@@ -2756,7 +2986,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2756
2986
|
},
|
|
2757
2987
|
onCancel: () => setVisibilityMode(false)
|
|
2758
2988
|
}
|
|
2759
|
-
) }) : sortMode ? /* @__PURE__ */
|
|
2989
|
+
) }) : sortMode ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
2760
2990
|
SortModal,
|
|
2761
2991
|
{
|
|
2762
2992
|
currentSort: sortKey,
|
|
@@ -2768,7 +2998,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2768
2998
|
},
|
|
2769
2999
|
onCancel: () => setSortMode(false)
|
|
2770
3000
|
}
|
|
2771
|
-
) }) : changeVisibilityMode && changeVisibilityTarget ? /* @__PURE__ */
|
|
3001
|
+
) }) : changeVisibilityMode && changeVisibilityTarget ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
2772
3002
|
ChangeVisibilityModal,
|
|
2773
3003
|
{
|
|
2774
3004
|
isOpen: changeVisibilityMode,
|
|
@@ -2781,8 +3011,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2781
3011
|
changing: changingVisibility,
|
|
2782
3012
|
error: changeVisibilityError
|
|
2783
3013
|
}
|
|
2784
|
-
) }) : /* @__PURE__ */
|
|
2785
|
-
|
|
3014
|
+
) }) : copyUrlMode ? /* @__PURE__ */ jsx16(Box15, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx16(
|
|
3015
|
+
CopyUrlModal,
|
|
3016
|
+
{
|
|
3017
|
+
repo: copyUrlTarget,
|
|
3018
|
+
terminalWidth,
|
|
3019
|
+
onClose: closeCopyUrlModal,
|
|
3020
|
+
onCopy: handleCopyUrl
|
|
3021
|
+
}
|
|
3022
|
+
) }) : /* @__PURE__ */ jsxs15(Fragment8, { children: [
|
|
3023
|
+
/* @__PURE__ */ jsx16(
|
|
2786
3024
|
RepoListHeader,
|
|
2787
3025
|
{
|
|
2788
3026
|
ownerContext,
|
|
@@ -2796,9 +3034,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2796
3034
|
isEnterprise: isEnterpriseOrg
|
|
2797
3035
|
}
|
|
2798
3036
|
),
|
|
2799
|
-
filterMode && /* @__PURE__ */
|
|
2800
|
-
/* @__PURE__ */
|
|
2801
|
-
/* @__PURE__ */
|
|
3037
|
+
filterMode && /* @__PURE__ */ jsxs15(Box15, { marginBottom: 1, children: [
|
|
3038
|
+
/* @__PURE__ */ jsx16(Text16, { children: "Search: " }),
|
|
3039
|
+
/* @__PURE__ */ jsx16(
|
|
2802
3040
|
TextInput5,
|
|
2803
3041
|
{
|
|
2804
3042
|
value: filter,
|
|
@@ -2838,10 +3076,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2838
3076
|
}
|
|
2839
3077
|
)
|
|
2840
3078
|
] }),
|
|
2841
|
-
/* @__PURE__ */
|
|
2842
|
-
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */
|
|
3079
|
+
/* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: listHeight, children: [
|
|
3080
|
+
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */ jsx16(Box15, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: "Type at least 3 characters to search" }) }) : visibleItems.slice(windowed.start, windowed.end).map((repo, i) => {
|
|
2843
3081
|
const idx = windowed.start + i;
|
|
2844
|
-
return /* @__PURE__ */
|
|
3082
|
+
return /* @__PURE__ */ jsx16(
|
|
2845
3083
|
RepoRow,
|
|
2846
3084
|
{
|
|
2847
3085
|
repo,
|
|
@@ -2854,32 +3092,33 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2854
3092
|
repo.nameWithOwner
|
|
2855
3093
|
);
|
|
2856
3094
|
}),
|
|
2857
|
-
loadingMore && hasNextPage && /* @__PURE__ */
|
|
2858
|
-
/* @__PURE__ */
|
|
2859
|
-
/* @__PURE__ */
|
|
3095
|
+
loadingMore && hasNextPage && /* @__PURE__ */ jsx16(Box15, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", children: [
|
|
3096
|
+
/* @__PURE__ */ jsx16(Box15, { width: 2, flexShrink: 0, flexGrow: 0, marginRight: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "cyan", children: /* @__PURE__ */ jsx16(SlowSpinner, {}) }) }),
|
|
3097
|
+
/* @__PURE__ */ jsx16(Text16, { color: "cyan", children: "Loading more repositories..." })
|
|
2860
3098
|
] }) }),
|
|
2861
|
-
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */
|
|
3099
|
+
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */ jsx16(Box15, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: true, children: searchActive ? "No repositories match your search" : filter ? "No repositories match your filter" : "No repositories found" }) })
|
|
2862
3100
|
] })
|
|
2863
3101
|
] }) }),
|
|
2864
|
-
/* @__PURE__ */
|
|
2865
|
-
/* @__PURE__ */
|
|
2866
|
-
/* @__PURE__ */
|
|
2867
|
-
/* @__PURE__ */
|
|
3102
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
3103
|
+
/* @__PURE__ */ jsx16(Box15, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: modalOpen ? true : void 0, children: "\u2191\u2193 Navigate \u2022 \u23CE/O Open \u2022 R Refresh \u2022 W Org Switch \u2022 Ctrl+L Logout \u2022 Q Quit" }) }),
|
|
3104
|
+
/* @__PURE__ */ jsx16(Box15, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: modalOpen ? true : void 0, children: "Ctrl+G Top \u2022 G Bottom \u2022 / Search \u2022 S Sort \u2022 D Direction \u2022 T Density \u2022 F Fork Status \u2022 V Visibility" }) }),
|
|
3105
|
+
/* @__PURE__ */ jsx16(Box15, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx16(Text16, { color: "gray", dimColor: modalOpen ? true : void 0, children: "I Info \u2022 C Copy URL \u2022 K Cache Info \u2022 Ctrl+R Rename \u2022 Ctrl+A Un/Archive \u2022 Ctrl+V Change Visibility \u2022 Del/Backspace Delete \u2022 Ctrl+S Sync Fork" }) })
|
|
2868
3106
|
] }),
|
|
2869
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
2870
|
-
/* @__PURE__ */
|
|
2871
|
-
debugMessages.length === 0 ? /* @__PURE__ */
|
|
2872
|
-
] })
|
|
3107
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [
|
|
3108
|
+
/* @__PURE__ */ jsx16(Text16, { bold: true, color: "yellow", children: "Debug Messages:" }),
|
|
3109
|
+
debugMessages.length === 0 ? /* @__PURE__ */ jsx16(Text16, { color: "gray", children: "No debug messages yet..." }) : debugMessages.map((msg, i) => /* @__PURE__ */ jsx16(Text16, { color: "gray", children: msg }, i))
|
|
3110
|
+
] }),
|
|
3111
|
+
copyToast && /* @__PURE__ */ jsx16(Box15, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx16(Box15, { borderStyle: "round", borderColor: copyToast.includes("Failed") ? "red" : "green", paddingX: 2, paddingY: 0, children: /* @__PURE__ */ jsx16(Text16, { color: copyToast.includes("Failed") ? "red" : "green", children: copyToast }) }) })
|
|
2873
3112
|
] });
|
|
2874
3113
|
}
|
|
2875
3114
|
|
|
2876
3115
|
// src/ui/components/auth/AuthMethodSelector.tsx
|
|
2877
|
-
import { useState as
|
|
2878
|
-
import { Box as
|
|
2879
|
-
import
|
|
2880
|
-
import { jsx as
|
|
3116
|
+
import { useState as useState13 } from "react";
|
|
3117
|
+
import { Box as Box16, Text as Text17, useInput as useInput13 } from "ink";
|
|
3118
|
+
import chalk13 from "chalk";
|
|
3119
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2881
3120
|
function AuthMethodSelector({ onSelect, onQuit }) {
|
|
2882
|
-
const [selectedIndex, setSelectedIndex] =
|
|
3121
|
+
const [selectedIndex, setSelectedIndex] = useState13(0);
|
|
2883
3122
|
const methods = [
|
|
2884
3123
|
{
|
|
2885
3124
|
key: "oauth",
|
|
@@ -2892,7 +3131,7 @@ function AuthMethodSelector({ onSelect, onQuit }) {
|
|
|
2892
3131
|
description: "Manually enter a GitHub Personal Access Token"
|
|
2893
3132
|
}
|
|
2894
3133
|
];
|
|
2895
|
-
|
|
3134
|
+
useInput13((input, key) => {
|
|
2896
3135
|
if (key.escape || input?.toLowerCase() === "q") {
|
|
2897
3136
|
if (onQuit) {
|
|
2898
3137
|
onQuit();
|
|
@@ -2911,34 +3150,34 @@ function AuthMethodSelector({ onSelect, onQuit }) {
|
|
|
2911
3150
|
onSelect("pat");
|
|
2912
3151
|
}
|
|
2913
3152
|
});
|
|
2914
|
-
return /* @__PURE__ */
|
|
2915
|
-
/* @__PURE__ */
|
|
2916
|
-
/* @__PURE__ */
|
|
3153
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 2, paddingY: 1, children: [
|
|
3154
|
+
/* @__PURE__ */ jsx17(Text17, { bold: true, marginBottom: 1, children: "Choose Authentication Method" }),
|
|
3155
|
+
/* @__PURE__ */ jsx17(Box16, { flexDirection: "column", marginY: 1, children: methods.map((method, index) => {
|
|
2917
3156
|
const isSelected = index === selectedIndex;
|
|
2918
|
-
const prefix = isSelected ?
|
|
3157
|
+
const prefix = isSelected ? chalk13.cyan("\u203A") : " ";
|
|
2919
3158
|
const numberPrefix = `${index + 1}.`;
|
|
2920
|
-
return /* @__PURE__ */
|
|
2921
|
-
/* @__PURE__ */
|
|
3159
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
3160
|
+
/* @__PURE__ */ jsx17(Text17, { children: /* @__PURE__ */ jsxs16(Text17, { color: isSelected ? "cyan" : void 0, bold: isSelected, children: [
|
|
2922
3161
|
prefix,
|
|
2923
3162
|
" ",
|
|
2924
3163
|
numberPrefix,
|
|
2925
3164
|
" ",
|
|
2926
3165
|
method.label
|
|
2927
3166
|
] }) }),
|
|
2928
|
-
/* @__PURE__ */
|
|
3167
|
+
/* @__PURE__ */ jsxs16(Text17, { color: "gray", dimColor: true, children: [
|
|
2929
3168
|
" ",
|
|
2930
3169
|
method.description
|
|
2931
3170
|
] })
|
|
2932
3171
|
] }, method.key);
|
|
2933
3172
|
}) }),
|
|
2934
|
-
/* @__PURE__ */
|
|
3173
|
+
/* @__PURE__ */ jsx17(Text17, { color: "gray", dimColor: true, marginTop: 1, children: "Use arrow keys to navigate, Enter to select, or press 1/2 \u2022 Q/Esc to quit" })
|
|
2935
3174
|
] });
|
|
2936
3175
|
}
|
|
2937
3176
|
|
|
2938
3177
|
// src/ui/components/auth/OAuthProgress.tsx
|
|
2939
|
-
import { Box as
|
|
3178
|
+
import { Box as Box17, Text as Text18 } from "ink";
|
|
2940
3179
|
import Spinner from "ink-spinner";
|
|
2941
|
-
import { jsx as
|
|
3180
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2942
3181
|
function OAuthProgress({ status, error, deviceCode }) {
|
|
2943
3182
|
const statusMessages = {
|
|
2944
3183
|
initializing: {
|
|
@@ -2975,64 +3214,64 @@ function OAuthProgress({ status, error, deviceCode }) {
|
|
|
2975
3214
|
}
|
|
2976
3215
|
};
|
|
2977
3216
|
const { message, showSpinner } = statusMessages[status];
|
|
2978
|
-
return /* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
2982
|
-
/* @__PURE__ */
|
|
3217
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", borderStyle: "single", borderColor: status === "error" ? "red" : "cyan", paddingX: 2, paddingY: 1, children: [
|
|
3218
|
+
/* @__PURE__ */ jsx18(Text18, { bold: true, marginBottom: 1, children: "GitHub OAuth Authentication" }),
|
|
3219
|
+
/* @__PURE__ */ jsx18(Box17, { marginY: 1, children: showSpinner ? /* @__PURE__ */ jsxs17(Box17, { children: [
|
|
3220
|
+
/* @__PURE__ */ jsx18(Text18, { color: "green", children: /* @__PURE__ */ jsx18(Spinner, { type: "dots" }) }),
|
|
3221
|
+
/* @__PURE__ */ jsxs17(Text18, { children: [
|
|
2983
3222
|
" ",
|
|
2984
3223
|
message
|
|
2985
3224
|
] })
|
|
2986
|
-
] }) : /* @__PURE__ */
|
|
3225
|
+
] }) : /* @__PURE__ */ jsxs17(Text18, { color: status === "error" ? "red" : "green", children: [
|
|
2987
3226
|
status === "error" ? "\u2717" : "\u2713",
|
|
2988
3227
|
" ",
|
|
2989
3228
|
message
|
|
2990
3229
|
] }) }),
|
|
2991
|
-
(status === "waiting_for_authorization" || status === "polling_for_token") && deviceCode && /* @__PURE__ */
|
|
2992
|
-
/* @__PURE__ */
|
|
2993
|
-
/* @__PURE__ */
|
|
2994
|
-
/* @__PURE__ */
|
|
2995
|
-
/* @__PURE__ */
|
|
3230
|
+
(status === "waiting_for_authorization" || status === "polling_for_token") && deviceCode && /* @__PURE__ */ jsxs17(Box17, { marginY: 1, flexDirection: "column", children: [
|
|
3231
|
+
/* @__PURE__ */ jsx18(Text18, { bold: true, color: "cyan", marginBottom: 1, children: "\u{1F4CB} Please complete these steps:" }),
|
|
3232
|
+
/* @__PURE__ */ jsxs17(Box17, { marginBottom: 1, children: [
|
|
3233
|
+
/* @__PURE__ */ jsx18(Text18, { children: "1. Visit: " }),
|
|
3234
|
+
/* @__PURE__ */ jsx18(Text18, { bold: true, color: "blue", children: deviceCode.verification_uri })
|
|
2996
3235
|
] }),
|
|
2997
|
-
/* @__PURE__ */
|
|
2998
|
-
/* @__PURE__ */
|
|
2999
|
-
/* @__PURE__ */
|
|
3236
|
+
/* @__PURE__ */ jsxs17(Box17, { marginBottom: 1, flexDirection: "column", children: [
|
|
3237
|
+
/* @__PURE__ */ jsx18(Text18, { children: "2. Enter this code:" }),
|
|
3238
|
+
/* @__PURE__ */ jsx18(Box17, { borderStyle: "single", borderColor: "yellow", paddingX: 2, paddingY: 1, marginTop: 1, children: /* @__PURE__ */ jsx18(Text18, { bold: true, color: "yellow", children: deviceCode.user_code }) })
|
|
3000
3239
|
] }),
|
|
3001
|
-
status === "waiting_for_authorization" && /* @__PURE__ */
|
|
3002
|
-
status === "polling_for_token" && /* @__PURE__ */
|
|
3003
|
-
/* @__PURE__ */
|
|
3004
|
-
/* @__PURE__ */
|
|
3240
|
+
status === "waiting_for_authorization" && /* @__PURE__ */ jsx18(Text18, { color: "gray", marginTop: 1, children: "Your browser should open automatically." }),
|
|
3241
|
+
status === "polling_for_token" && /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", marginTop: 1, children: [
|
|
3242
|
+
/* @__PURE__ */ jsx18(Text18, { color: "gray", children: "Waiting for you to complete authorization in your browser..." }),
|
|
3243
|
+
/* @__PURE__ */ jsx18(Text18, { color: "gray", dimColor: true, marginTop: 1, children: "This will timeout in 15 minutes. Press Esc to cancel." })
|
|
3005
3244
|
] })
|
|
3006
3245
|
] }),
|
|
3007
|
-
status === "error" && error && /* @__PURE__ */
|
|
3008
|
-
/* @__PURE__ */
|
|
3009
|
-
/* @__PURE__ */
|
|
3246
|
+
status === "error" && error && /* @__PURE__ */ jsxs17(Box17, { marginY: 1, flexDirection: "column", children: [
|
|
3247
|
+
/* @__PURE__ */ jsx18(Text18, { color: "red", children: error }),
|
|
3248
|
+
/* @__PURE__ */ jsx18(Text18, { color: "gray", marginTop: 1, children: "Press Esc to go back and try again." })
|
|
3010
3249
|
] }),
|
|
3011
|
-
status === "success" && /* @__PURE__ */
|
|
3250
|
+
status === "success" && /* @__PURE__ */ jsx18(Text18, { color: "gray", marginTop: 1, children: "Returning to application..." })
|
|
3012
3251
|
] });
|
|
3013
3252
|
}
|
|
3014
3253
|
|
|
3015
3254
|
// src/ui/App.tsx
|
|
3016
|
-
import { jsx as
|
|
3255
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3017
3256
|
var packageJson = require_package();
|
|
3018
3257
|
function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlineTokenEphemeral }) {
|
|
3019
3258
|
const { exit } = useApp2();
|
|
3020
3259
|
const { stdout } = useStdout2();
|
|
3021
|
-
const [mode, setMode] =
|
|
3022
|
-
const [token, setToken] =
|
|
3023
|
-
const [input, setInput] =
|
|
3024
|
-
const [error, setError] =
|
|
3025
|
-
const [viewer, setViewer] =
|
|
3026
|
-
const [rateLimitReset, setRateLimitReset] =
|
|
3027
|
-
const [wasRateLimited, setWasRateLimited] =
|
|
3028
|
-
const [orgContext, setOrgContext] =
|
|
3029
|
-
const [authMethod, setAuthMethod] =
|
|
3030
|
-
const [oauthStatus, setOAuthStatus] =
|
|
3031
|
-
const [tokenSource, setTokenSource] =
|
|
3032
|
-
const [sessionTokenOrigin, setSessionTokenOrigin] =
|
|
3033
|
-
const [deviceCodeResponse, setDeviceCodeResponse] =
|
|
3034
|
-
const [oauthDeviceCode, setOauthDeviceCode] =
|
|
3035
|
-
const [dims, setDims] =
|
|
3260
|
+
const [mode, setMode] = useState14("checking");
|
|
3261
|
+
const [token, setToken] = useState14(null);
|
|
3262
|
+
const [input, setInput] = useState14("");
|
|
3263
|
+
const [error, setError] = useState14(null);
|
|
3264
|
+
const [viewer, setViewer] = useState14(null);
|
|
3265
|
+
const [rateLimitReset, setRateLimitReset] = useState14(null);
|
|
3266
|
+
const [wasRateLimited, setWasRateLimited] = useState14(false);
|
|
3267
|
+
const [orgContext, setOrgContext] = useState14("personal");
|
|
3268
|
+
const [authMethod, setAuthMethod] = useState14("pat");
|
|
3269
|
+
const [oauthStatus, setOAuthStatus] = useState14("initializing");
|
|
3270
|
+
const [tokenSource, setTokenSource] = useState14("pat");
|
|
3271
|
+
const [sessionTokenOrigin, setSessionTokenOrigin] = useState14("stored");
|
|
3272
|
+
const [deviceCodeResponse, setDeviceCodeResponse] = useState14(null);
|
|
3273
|
+
const [oauthDeviceCode, setOauthDeviceCode] = useState14(null);
|
|
3274
|
+
const [dims, setDims] = useState14(() => {
|
|
3036
3275
|
const cols = stdout?.columns ?? 100;
|
|
3037
3276
|
const rows = stdout?.rows ?? 30;
|
|
3038
3277
|
return { cols, rows };
|
|
@@ -3237,7 +3476,7 @@ function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlin
|
|
|
3237
3476
|
setTokenSource("pat");
|
|
3238
3477
|
setMode("auth_method_selection");
|
|
3239
3478
|
};
|
|
3240
|
-
|
|
3479
|
+
useInput14((input2, key) => {
|
|
3241
3480
|
if ((mode === "prompt" || mode === "auth_method_selection") && key.escape) {
|
|
3242
3481
|
exit();
|
|
3243
3482
|
}
|
|
@@ -3269,19 +3508,19 @@ function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlin
|
|
|
3269
3508
|
}
|
|
3270
3509
|
});
|
|
3271
3510
|
const verticalPadding = Math.floor(dims.rows * 0.15);
|
|
3272
|
-
const header = useMemo2(() => /* @__PURE__ */
|
|
3273
|
-
/* @__PURE__ */
|
|
3274
|
-
/* @__PURE__ */
|
|
3511
|
+
const header = useMemo2(() => /* @__PURE__ */ jsxs18(Box18, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [
|
|
3512
|
+
/* @__PURE__ */ jsxs18(Box18, { flexDirection: "row", gap: 1, children: [
|
|
3513
|
+
/* @__PURE__ */ jsxs18(Text19, { bold: true, color: "cyan", children: [
|
|
3275
3514
|
" ",
|
|
3276
3515
|
"GitHub Repository Manager"
|
|
3277
3516
|
] }),
|
|
3278
|
-
/* @__PURE__ */
|
|
3517
|
+
/* @__PURE__ */ jsxs18(Text19, { color: "gray", dimColor: true, children: [
|
|
3279
3518
|
"v",
|
|
3280
3519
|
packageJson.version
|
|
3281
3520
|
] }),
|
|
3282
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
3521
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsx19(Text19, { backgroundColor: "blue", color: "white", children: " debug mode " })
|
|
3283
3522
|
] }),
|
|
3284
|
-
viewer && /* @__PURE__ */
|
|
3523
|
+
viewer && /* @__PURE__ */ jsx19(Text19, { color: "gray", children: orgContext !== "personal" && orgContext.login ? `${orgContext.login}/@${viewer} ` : `@${viewer} ` })
|
|
3285
3524
|
] }), [viewer, orgContext]);
|
|
3286
3525
|
if (mode === "rate_limited") {
|
|
3287
3526
|
const formatResetTime = (resetTime) => {
|
|
@@ -3304,70 +3543,70 @@ function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlin
|
|
|
3304
3543
|
return "Unknown";
|
|
3305
3544
|
}
|
|
3306
3545
|
};
|
|
3307
|
-
return /* @__PURE__ */
|
|
3546
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3308
3547
|
header,
|
|
3309
|
-
/* @__PURE__ */
|
|
3310
|
-
/* @__PURE__ */
|
|
3311
|
-
/* @__PURE__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3313
|
-
rateLimitReset && /* @__PURE__ */
|
|
3314
|
-
/* @__PURE__ */
|
|
3315
|
-
/* @__PURE__ */
|
|
3548
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs18(Box18, { borderStyle: "single", borderColor: "yellow", paddingX: 3, paddingY: 2, flexDirection: "column", width: Math.min(dims.cols - 8, 80), children: [
|
|
3549
|
+
/* @__PURE__ */ jsx19(Text19, { bold: true, color: "yellow", marginBottom: 1, children: "\u26A0\uFE0F Rate Limit Exceeded" }),
|
|
3550
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", marginBottom: 1, children: "You've hit GitHub's API rate limit for your token." }),
|
|
3551
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", marginBottom: 1, children: "This happens when you make too many requests in a short time." }),
|
|
3552
|
+
rateLimitReset && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, marginBottom: 1, children: [
|
|
3553
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
3554
|
+
/* @__PURE__ */ jsx19(Text19, { color: "cyan", children: "Reset in:" }),
|
|
3316
3555
|
" ",
|
|
3317
|
-
/* @__PURE__ */
|
|
3556
|
+
/* @__PURE__ */ jsx19(Text19, { bold: true, children: formatResetTime(rateLimitReset) })
|
|
3318
3557
|
] }),
|
|
3319
|
-
/* @__PURE__ */
|
|
3558
|
+
/* @__PURE__ */ jsxs18(Text19, { color: "gray", dimColor: true, children: [
|
|
3320
3559
|
"(",
|
|
3321
3560
|
new Date(rateLimitReset).toLocaleTimeString(),
|
|
3322
3561
|
")"
|
|
3323
3562
|
] })
|
|
3324
3563
|
] }),
|
|
3325
|
-
/* @__PURE__ */
|
|
3326
|
-
/* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
3328
|
-
/* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
3564
|
+
/* @__PURE__ */ jsxs18(Box18, { marginTop: 2, flexDirection: "column", gap: 1, children: [
|
|
3565
|
+
/* @__PURE__ */ jsx19(Text19, { bold: true, children: "What would you like to do?" }),
|
|
3566
|
+
/* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", paddingLeft: 2, children: [
|
|
3567
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
3568
|
+
/* @__PURE__ */ jsx19(Text19, { color: "cyan", bold: true, children: "R" }),
|
|
3330
3569
|
" - Retry now ",
|
|
3331
3570
|
rateLimitReset && formatResetTime(rateLimitReset) !== "Now (should be reset)" ? "(likely to fail until reset)" : "(should work now)"
|
|
3332
3571
|
] }),
|
|
3333
|
-
/* @__PURE__ */
|
|
3334
|
-
/* @__PURE__ */
|
|
3572
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
3573
|
+
/* @__PURE__ */ jsx19(Text19, { color: "cyan", bold: true, children: "L" }),
|
|
3335
3574
|
" - Logout and choose authentication method"
|
|
3336
3575
|
] }),
|
|
3337
|
-
/* @__PURE__ */
|
|
3338
|
-
/* @__PURE__ */
|
|
3576
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
3577
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", bold: true, children: "Q/Esc" }),
|
|
3339
3578
|
" - Quit application"
|
|
3340
3579
|
] })
|
|
3341
3580
|
] })
|
|
3342
3581
|
] }),
|
|
3343
|
-
/* @__PURE__ */
|
|
3582
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: true, marginTop: 2, children: "Tip: Using multiple tokens or waiting between requests can help avoid rate limits." })
|
|
3344
3583
|
] }) })
|
|
3345
3584
|
] });
|
|
3346
3585
|
}
|
|
3347
3586
|
if (mode === "auth_method_selection") {
|
|
3348
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3349
3588
|
header,
|
|
3350
|
-
/* @__PURE__ */
|
|
3351
|
-
/* @__PURE__ */
|
|
3352
|
-
error && /* @__PURE__ */
|
|
3589
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", alignItems: "center", children: [
|
|
3590
|
+
/* @__PURE__ */ jsx19(AuthMethodSelector, { onSelect: handleAuthMethodSelect }),
|
|
3591
|
+
error && /* @__PURE__ */ jsx19(Text19, { color: "red", marginTop: 1, children: error })
|
|
3353
3592
|
] }) })
|
|
3354
3593
|
] });
|
|
3355
3594
|
}
|
|
3356
3595
|
if (mode === "oauth_flow") {
|
|
3357
|
-
return /* @__PURE__ */
|
|
3596
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3358
3597
|
header,
|
|
3359
|
-
/* @__PURE__ */
|
|
3598
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx19(OAuthProgress, { status: oauthStatus, error: error || void 0, deviceCode: oauthDeviceCode || void 0 }) })
|
|
3360
3599
|
] });
|
|
3361
3600
|
}
|
|
3362
3601
|
if (mode === "prompt") {
|
|
3363
|
-
return /* @__PURE__ */
|
|
3602
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3364
3603
|
header,
|
|
3365
|
-
/* @__PURE__ */
|
|
3366
|
-
/* @__PURE__ */
|
|
3367
|
-
/* @__PURE__ */
|
|
3368
|
-
/* @__PURE__ */
|
|
3369
|
-
/* @__PURE__ */
|
|
3370
|
-
/* @__PURE__ */
|
|
3604
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs18(Box18, { borderStyle: "single", borderColor: "cyan", paddingX: 2, paddingY: 1, flexDirection: "column", children: [
|
|
3605
|
+
/* @__PURE__ */ jsx19(Text19, { bold: true, marginBottom: 1, children: "Authentication Required" }),
|
|
3606
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", marginBottom: 1, children: "Enter your GitHub Personal Access Token" }),
|
|
3607
|
+
/* @__PURE__ */ jsxs18(Box18, { children: [
|
|
3608
|
+
/* @__PURE__ */ jsx19(Text19, { children: "Token: " }),
|
|
3609
|
+
/* @__PURE__ */ jsx19(
|
|
3371
3610
|
TextInput6,
|
|
3372
3611
|
{
|
|
3373
3612
|
value: input,
|
|
@@ -3377,30 +3616,30 @@ function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlin
|
|
|
3377
3616
|
}
|
|
3378
3617
|
)
|
|
3379
3618
|
] }),
|
|
3380
|
-
error && /* @__PURE__ */
|
|
3381
|
-
/* @__PURE__ */
|
|
3382
|
-
/* @__PURE__ */
|
|
3619
|
+
error && /* @__PURE__ */ jsx19(Text19, { color: "red", marginTop: 1, children: error }),
|
|
3620
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: true, marginTop: 1, children: "The token will be stored securely in your local config" }),
|
|
3621
|
+
/* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to go back" })
|
|
3383
3622
|
] }) })
|
|
3384
3623
|
] });
|
|
3385
3624
|
}
|
|
3386
3625
|
if (mode === "validating" || mode === "checking") {
|
|
3387
|
-
return /* @__PURE__ */
|
|
3626
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3388
3627
|
header,
|
|
3389
|
-
/* @__PURE__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
3391
|
-
mode === "validating" && /* @__PURE__ */
|
|
3628
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", alignItems: "center", children: [
|
|
3629
|
+
/* @__PURE__ */ jsx19(Text19, { color: "yellow", children: "Validating token..." }),
|
|
3630
|
+
mode === "validating" && /* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to cancel" })
|
|
3392
3631
|
] }) })
|
|
3393
3632
|
] });
|
|
3394
3633
|
}
|
|
3395
3634
|
if (mode === "error") {
|
|
3396
|
-
return /* @__PURE__ */
|
|
3635
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3397
3636
|
header,
|
|
3398
|
-
/* @__PURE__ */
|
|
3637
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx19(Text19, { color: "red", children: error ?? "Unexpected error" }) })
|
|
3399
3638
|
] });
|
|
3400
3639
|
}
|
|
3401
|
-
return /* @__PURE__ */
|
|
3640
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
3402
3641
|
header,
|
|
3403
|
-
/* @__PURE__ */
|
|
3642
|
+
/* @__PURE__ */ jsx19(
|
|
3404
3643
|
RepoList,
|
|
3405
3644
|
{
|
|
3406
3645
|
token,
|
|
@@ -3415,7 +3654,7 @@ function App({ initialOrgSlug: initialOrgSlug2, inlineToken: inlineToken2, inlin
|
|
|
3415
3654
|
}
|
|
3416
3655
|
|
|
3417
3656
|
// src/index.tsx
|
|
3418
|
-
import { jsx as
|
|
3657
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3419
3658
|
var argv = process.argv.slice(2);
|
|
3420
3659
|
var getFlagValue = (name) => {
|
|
3421
3660
|
const idx = argv.findIndex((a) => a === `--${name}` || a.startsWith(`--${name}=`));
|
|
@@ -3510,8 +3749,8 @@ var inlineToken = (() => {
|
|
|
3510
3749
|
})();
|
|
3511
3750
|
logger.debug("Rendering UI");
|
|
3512
3751
|
var { unmount } = render(
|
|
3513
|
-
/* @__PURE__ */
|
|
3514
|
-
/* @__PURE__ */
|
|
3515
|
-
/* @__PURE__ */
|
|
3752
|
+
/* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
|
|
3753
|
+
/* @__PURE__ */ jsx20(App, { initialOrgSlug, inlineToken, inlineTokenEphemeral: Boolean(inlineToken) }),
|
|
3754
|
+
/* @__PURE__ */ jsx20(Text20, { color: "gray" })
|
|
3516
3755
|
] })
|
|
3517
3756
|
);
|