gh-manager-cli 1.45.0 → 1.45.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/dist/index.js +28 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.45.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.45.0...v1.45.1) (2026-06-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* ignore modal input while async actions are in flight, add guard tests (SWR-368) [semantic pr title] ([#64](https://github.com/wiiiimm/gh-manager-cli/issues/64)) ([97d2e4e](https://github.com/wiiiimm/gh-manager-cli/commit/97d2e4e25fc5d10cd2305ffb3f594b3f0b094e20)), closes [#65](https://github.com/wiiiimm/gh-manager-cli/issues/65)
|
|
7
|
+
|
|
1
8
|
# [1.45.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.44.0...v1.45.0) (2026-06-07)
|
|
2
9
|
|
|
3
10
|
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ var require_package = __commonJS({
|
|
|
37
37
|
"package.json"(exports, module) {
|
|
38
38
|
module.exports = {
|
|
39
39
|
name: "gh-manager-cli",
|
|
40
|
-
version: "1.45.
|
|
40
|
+
version: "1.45.1",
|
|
41
41
|
private: false,
|
|
42
42
|
description: "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
43
43
|
license: "MIT",
|
|
@@ -411,7 +411,7 @@ async function openGitHubAuthorizationPage() {
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
// src/ui/views/RepoList.tsx
|
|
414
|
-
import React19, { useEffect as useEffect13, useMemo as useMemo2, useState as useState19, useRef as
|
|
414
|
+
import React19, { useEffect as useEffect13, useMemo as useMemo2, useState as useState19, useRef as useRef7, useCallback } from "react";
|
|
415
415
|
import { Box as Box22, Text as Text23, useApp, useInput as useInput19, useStdout } from "ink";
|
|
416
416
|
import TextInput7 from "ink-text-input";
|
|
417
417
|
import chalk15 from "chalk";
|
|
@@ -813,7 +813,7 @@ function ArchiveFilterModal({
|
|
|
813
813
|
}
|
|
814
814
|
|
|
815
815
|
// src/ui/components/modals/DeleteModal.tsx
|
|
816
|
-
import {
|
|
816
|
+
import { useEffect as useEffect4, useRef, useState as useState4 } from "react";
|
|
817
817
|
import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
|
|
818
818
|
import TextInput from "ink-text-input";
|
|
819
819
|
import chalk4 from "chalk";
|
|
@@ -838,13 +838,13 @@ function SlowSpinner({ interval = 500 } = {}) {
|
|
|
838
838
|
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
839
839
|
|
|
840
840
|
// src/ui/components/modals/ArchiveModal.tsx
|
|
841
|
-
import { useState as useState5 } from "react";
|
|
841
|
+
import { useRef as useRef2, useState as useState5 } from "react";
|
|
842
842
|
import { Box as Box4, Text as Text5, useInput as useInput4 } from "ink";
|
|
843
843
|
import chalk5 from "chalk";
|
|
844
844
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
845
845
|
|
|
846
846
|
// src/ui/components/modals/SyncModal.tsx
|
|
847
|
-
import { useState as useState6 } from "react";
|
|
847
|
+
import { useRef as useRef3, useState as useState6 } from "react";
|
|
848
848
|
import { Box as Box5, Text as Text6, useInput as useInput5 } from "ink";
|
|
849
849
|
import chalk6 from "chalk";
|
|
850
850
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -1370,6 +1370,7 @@ var ChangeVisibilityModal = ({
|
|
|
1370
1370
|
}, [isOpen, isFork]);
|
|
1371
1371
|
useInput11((input, key) => {
|
|
1372
1372
|
if (!isOpen) return;
|
|
1373
|
+
if (changing) return;
|
|
1373
1374
|
if (key.escape || input?.toLowerCase() === "c") {
|
|
1374
1375
|
onClose();
|
|
1375
1376
|
return;
|
|
@@ -1523,6 +1524,7 @@ var ChangeVisibilityModal = ({
|
|
|
1523
1524
|
onChange: () => {
|
|
1524
1525
|
},
|
|
1525
1526
|
onSubmit: () => {
|
|
1527
|
+
if (changing) return;
|
|
1526
1528
|
if (isFork || focusedButton === "cancel") {
|
|
1527
1529
|
onClose();
|
|
1528
1530
|
} else {
|
|
@@ -1666,7 +1668,7 @@ function CopyUrlModal({ repo, terminalWidth, onClose, onCopy, theme: themeProp }
|
|
|
1666
1668
|
}
|
|
1667
1669
|
|
|
1668
1670
|
// src/ui/components/modals/RenameModal.tsx
|
|
1669
|
-
import {
|
|
1671
|
+
import { useEffect as useEffect9, useRef as useRef4, useState as useState13 } from "react";
|
|
1670
1672
|
import { Box as Box13, Text as Text14, useInput as useInput13 } from "ink";
|
|
1671
1673
|
import TextInput3 from "ink-text-input";
|
|
1672
1674
|
import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
@@ -1674,6 +1676,7 @@ function RenameModal({ repo, onRename, onCancel, theme: themeProp }) {
|
|
|
1674
1676
|
const { theme } = useTheme(themeProp?.name ?? "default");
|
|
1675
1677
|
const [newName, setNewName] = useState13("");
|
|
1676
1678
|
const [renaming, setRenaming] = useState13(false);
|
|
1679
|
+
const renamingRef = useRef4(false);
|
|
1677
1680
|
const [renameError, setRenameError] = useState13(null);
|
|
1678
1681
|
useEffect9(() => {
|
|
1679
1682
|
if (repo) {
|
|
@@ -1682,7 +1685,7 @@ function RenameModal({ repo, onRename, onCancel, theme: themeProp }) {
|
|
|
1682
1685
|
}
|
|
1683
1686
|
}, [repo]);
|
|
1684
1687
|
useInput13((input, key) => {
|
|
1685
|
-
if (
|
|
1688
|
+
if (renamingRef.current) return;
|
|
1686
1689
|
if (key.escape) {
|
|
1687
1690
|
onCancel();
|
|
1688
1691
|
return;
|
|
@@ -1695,13 +1698,15 @@ function RenameModal({ repo, onRename, onCancel, theme: themeProp }) {
|
|
|
1695
1698
|
}
|
|
1696
1699
|
});
|
|
1697
1700
|
const handleRenameConfirm = async () => {
|
|
1698
|
-
if (!repo ||
|
|
1701
|
+
if (!repo || renamingRef.current || !newName.trim() || newName === repo.name) return;
|
|
1699
1702
|
try {
|
|
1703
|
+
renamingRef.current = true;
|
|
1700
1704
|
setRenaming(true);
|
|
1701
1705
|
setRenameError(null);
|
|
1702
1706
|
await onRename(repo, newName.trim());
|
|
1703
1707
|
} catch (e) {
|
|
1704
1708
|
setRenameError(e.message || "Failed to rename repository");
|
|
1709
|
+
renamingRef.current = false;
|
|
1705
1710
|
setRenaming(false);
|
|
1706
1711
|
}
|
|
1707
1712
|
};
|
|
@@ -1777,6 +1782,7 @@ function StarModal({
|
|
|
1777
1782
|
const [focusedButton, setFocusedButton] = useState14("cancel");
|
|
1778
1783
|
useInput14((input, key) => {
|
|
1779
1784
|
if (!visible) return;
|
|
1785
|
+
if (isStarring) return;
|
|
1780
1786
|
if (key.escape || input === "c" || input === "C") {
|
|
1781
1787
|
onCancel();
|
|
1782
1788
|
return;
|
|
@@ -1948,7 +1954,7 @@ function OpenInBrowserModal({ repo, onOpen, onCancel, theme: themeProp }) {
|
|
|
1948
1954
|
}
|
|
1949
1955
|
|
|
1950
1956
|
// src/ui/components/modals/CreateRepoModal.tsx
|
|
1951
|
-
import { useState as useState16, useRef } from "react";
|
|
1957
|
+
import { useState as useState16, useRef as useRef5 } from "react";
|
|
1952
1958
|
import { Box as Box16, Text as Text17, useInput as useInput16 } from "ink";
|
|
1953
1959
|
import TextInput4 from "ink-text-input";
|
|
1954
1960
|
import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -1958,10 +1964,10 @@ function CreateRepoModal({ ownerSlug, isOrg, isEnterprise, onCreate, onCancel, t
|
|
|
1958
1964
|
const [visibility, setVisibility] = useState16("PRIVATE");
|
|
1959
1965
|
const [creating, setCreating] = useState16(false);
|
|
1960
1966
|
const [error, setError] = useState16(null);
|
|
1961
|
-
const submittingRef =
|
|
1967
|
+
const submittingRef = useRef5(false);
|
|
1962
1968
|
const visibilities = isOrg && isEnterprise ? ["PRIVATE", "PUBLIC", "INTERNAL"] : ["PRIVATE", "PUBLIC"];
|
|
1963
1969
|
useInput16((input, key) => {
|
|
1964
|
-
if (
|
|
1970
|
+
if (submittingRef.current) return;
|
|
1965
1971
|
if (key.escape) {
|
|
1966
1972
|
onCancel();
|
|
1967
1973
|
return;
|
|
@@ -2054,7 +2060,7 @@ function CreateRepoModal({ ownerSlug, isOrg, isEnterprise, onCreate, onCancel, t
|
|
|
2054
2060
|
}
|
|
2055
2061
|
|
|
2056
2062
|
// src/ui/components/modals/TransferModal.tsx
|
|
2057
|
-
import { useState as useState17, useRef as
|
|
2063
|
+
import { useState as useState17, useRef as useRef6, useEffect as useEffect11 } from "react";
|
|
2058
2064
|
import { Box as Box17, Text as Text18, useInput as useInput17 } from "ink";
|
|
2059
2065
|
import TextInput5 from "ink-text-input";
|
|
2060
2066
|
import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
@@ -2067,7 +2073,7 @@ function TransferModal({ repo, onTransfer, onCancel, theme: themeProp }) {
|
|
|
2067
2073
|
const [error, setError] = useState17(null);
|
|
2068
2074
|
const [transferCode, setTransferCode] = useState17("");
|
|
2069
2075
|
const [typedCode, setTypedCode] = useState17("");
|
|
2070
|
-
const submittingRef =
|
|
2076
|
+
const submittingRef = useRef6(false);
|
|
2071
2077
|
const owner = repo ? repo.nameWithOwner.split("/")[0] : "";
|
|
2072
2078
|
useEffect11(() => {
|
|
2073
2079
|
if (repo) {
|
|
@@ -2084,7 +2090,7 @@ function TransferModal({ repo, onTransfer, onCancel, theme: themeProp }) {
|
|
|
2084
2090
|
}
|
|
2085
2091
|
}, [repo]);
|
|
2086
2092
|
useInput17((input, key) => {
|
|
2087
|
-
if (
|
|
2093
|
+
if (submittingRef.current || !repo) return;
|
|
2088
2094
|
if (key.escape) {
|
|
2089
2095
|
onCancel();
|
|
2090
2096
|
return;
|
|
@@ -2299,6 +2305,7 @@ function UnstarModal({
|
|
|
2299
2305
|
const [focusedButton, setFocusedButton] = useState18("cancel");
|
|
2300
2306
|
useInput18((input, key) => {
|
|
2301
2307
|
if (!visible) return;
|
|
2308
|
+
if (isUnstarring) return;
|
|
2302
2309
|
if (key.escape || input === "c" || input === "C") {
|
|
2303
2310
|
onCancel();
|
|
2304
2311
|
return;
|
|
@@ -2528,7 +2535,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2528
2535
|
setDebugMessages((prev) => [...prev.slice(-9), msg]);
|
|
2529
2536
|
}
|
|
2530
2537
|
}, []);
|
|
2531
|
-
const handleOrgContextChangeRef =
|
|
2538
|
+
const handleOrgContextChangeRef = useRef7(onOrgContextChange);
|
|
2532
2539
|
useEffect13(() => {
|
|
2533
2540
|
handleOrgContextChangeRef.current = onOrgContextChange;
|
|
2534
2541
|
}, [onOrgContextChange]);
|
|
@@ -2562,7 +2569,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2562
2569
|
const [prefsLoaded, setPrefsLoaded] = useState19(false);
|
|
2563
2570
|
const [themeName, setThemeName] = useState19("default");
|
|
2564
2571
|
const [themeToast, setThemeToast] = useState19(null);
|
|
2565
|
-
const themeToastTimerRef =
|
|
2572
|
+
const themeToastTimerRef = useRef7(null);
|
|
2566
2573
|
const { theme, c: tc } = useTheme(themeName);
|
|
2567
2574
|
const [ownerContext, setOwnerContext] = useState19("personal");
|
|
2568
2575
|
const [ownerAffiliations, setOwnerAffiliations] = useState19(["OWNER"]);
|
|
@@ -2628,8 +2635,8 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2628
2635
|
const [openInBrowserMode, setOpenInBrowserMode] = useState19(false);
|
|
2629
2636
|
const [openInBrowserTarget, setOpenInBrowserTarget] = useState19(null);
|
|
2630
2637
|
const [enrichingForks, setEnrichingForks] = useState19(false);
|
|
2631
|
-
const enrichmentDoneRef =
|
|
2632
|
-
const appliedInitialOrg =
|
|
2638
|
+
const enrichmentDoneRef = useRef7(/* @__PURE__ */ new Set());
|
|
2639
|
+
const appliedInitialOrg = useRef7(false);
|
|
2633
2640
|
useEffect13(() => {
|
|
2634
2641
|
(async () => {
|
|
2635
2642
|
if (appliedInitialOrg.current) return;
|
|
@@ -2923,7 +2930,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2923
2930
|
trackSuccessfulOperation();
|
|
2924
2931
|
closeTransferModal();
|
|
2925
2932
|
}
|
|
2926
|
-
const copyToastTimerRef =
|
|
2933
|
+
const copyToastTimerRef = useRef7(null);
|
|
2927
2934
|
async function handleCopyUrl(url, type) {
|
|
2928
2935
|
try {
|
|
2929
2936
|
if (copyToastTimerRef.current) {
|
|
@@ -3127,8 +3134,8 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3127
3134
|
}
|
|
3128
3135
|
}
|
|
3129
3136
|
const [visibilityFilter, setVisibilityFilter] = useState19("all");
|
|
3130
|
-
const previousVisibilityFilter =
|
|
3131
|
-
const pendingFocusRef =
|
|
3137
|
+
const previousVisibilityFilter = useRef7("all");
|
|
3138
|
+
const pendingFocusRef = useRef7(null);
|
|
3132
3139
|
const [archiveFilter, setArchiveFilter] = useState19("all");
|
|
3133
3140
|
const sortFieldMap = {
|
|
3134
3141
|
"updated": "UPDATED_AT",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gh-manager-cli",
|
|
3
|
-
"version": "1.45.
|
|
3
|
+
"version": "1.45.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
6
6
|
"license": "MIT",
|