brew-tui 1.1.0 → 1.2.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/build/index.js
CHANGED
|
@@ -66,7 +66,7 @@ import { rm as rm2 } from "fs/promises";
|
|
|
66
66
|
import { render } from "ink";
|
|
67
67
|
|
|
68
68
|
// src/app.tsx
|
|
69
|
-
import { useEffect as
|
|
69
|
+
import { useEffect as useEffect22, useState as useState20 } from "react";
|
|
70
70
|
import { useApp } from "ink";
|
|
71
71
|
|
|
72
72
|
// src/components/layout/app-layout.tsx
|
|
@@ -77,28 +77,46 @@ import { Box as Box3 } from "ink";
|
|
|
77
77
|
import { Box, Text as Text3 } from "ink";
|
|
78
78
|
|
|
79
79
|
// src/hooks/use-terminal-size.ts
|
|
80
|
-
import {
|
|
80
|
+
import { useSyncExternalStore } from "react";
|
|
81
81
|
import { useStdout } from "ink";
|
|
82
|
+
var FALLBACK = { columns: 80, rows: 24 };
|
|
83
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
84
|
+
function snapshot(stdout) {
|
|
85
|
+
return {
|
|
86
|
+
columns: stdout.columns ?? FALLBACK.columns,
|
|
87
|
+
rows: stdout.rows ?? FALLBACK.rows
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function getCache(stdout) {
|
|
91
|
+
const existing = cache.get(stdout);
|
|
92
|
+
if (existing) return existing;
|
|
93
|
+
const entry = {
|
|
94
|
+
current: snapshot(stdout),
|
|
95
|
+
subscribers: /* @__PURE__ */ new Set()
|
|
96
|
+
};
|
|
97
|
+
cache.set(stdout, entry);
|
|
98
|
+
stdout.on("resize", () => {
|
|
99
|
+
entry.current = snapshot(stdout);
|
|
100
|
+
entry.subscribers.forEach((cb) => cb());
|
|
101
|
+
});
|
|
102
|
+
return entry;
|
|
103
|
+
}
|
|
82
104
|
function useTerminalSize() {
|
|
83
105
|
const { stdout } = useStdout();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
stdout.off("resize", onResize);
|
|
99
|
-
};
|
|
100
|
-
}, [stdout]);
|
|
101
|
-
return size;
|
|
106
|
+
return useSyncExternalStore(
|
|
107
|
+
(cb) => {
|
|
108
|
+
if (!stdout) return () => {
|
|
109
|
+
};
|
|
110
|
+
const entry = getCache(stdout);
|
|
111
|
+
entry.subscribers.add(cb);
|
|
112
|
+
return () => {
|
|
113
|
+
entry.subscribers.delete(cb);
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
() => stdout ? getCache(stdout).current : FALLBACK,
|
|
117
|
+
// Server snapshot — not used in CLI, but useSyncExternalStore requires it.
|
|
118
|
+
() => FALLBACK
|
|
119
|
+
);
|
|
102
120
|
}
|
|
103
121
|
|
|
104
122
|
// src/stores/navigation-store.ts
|
|
@@ -322,7 +340,7 @@ var GRADIENTS = {
|
|
|
322
340
|
};
|
|
323
341
|
|
|
324
342
|
// src/components/common/blinking-text.tsx
|
|
325
|
-
import { useEffect
|
|
343
|
+
import { useEffect, useState } from "react";
|
|
326
344
|
import { Text as Text2 } from "ink";
|
|
327
345
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
328
346
|
function BlinkingText({
|
|
@@ -331,8 +349,8 @@ function BlinkingText({
|
|
|
331
349
|
bold = true,
|
|
332
350
|
children
|
|
333
351
|
}) {
|
|
334
|
-
const [bright, setBright] =
|
|
335
|
-
|
|
352
|
+
const [bright, setBright] = useState(true);
|
|
353
|
+
useEffect(() => {
|
|
336
354
|
const id = setInterval(() => setBright((b) => !b), intervalMs);
|
|
337
355
|
return () => clearInterval(id);
|
|
338
356
|
}, [intervalMs]);
|
|
@@ -349,6 +367,20 @@ var SPACING = {
|
|
|
349
367
|
xl: 6,
|
|
350
368
|
xxl: 8
|
|
351
369
|
};
|
|
370
|
+
var BREAKPOINTS = {
|
|
371
|
+
/** Below this we collapse to single-column rows (only the name fits). */
|
|
372
|
+
narrow: 50,
|
|
373
|
+
/** Below this we drop the description column but keep version. */
|
|
374
|
+
mid: 80,
|
|
375
|
+
/** At or above this we render every column comfortably. */
|
|
376
|
+
wide: 120
|
|
377
|
+
};
|
|
378
|
+
function getLayoutMode(columns) {
|
|
379
|
+
if (columns < BREAKPOINTS.narrow) return "single";
|
|
380
|
+
if (columns < BREAKPOINTS.mid) return "compact";
|
|
381
|
+
if (columns < BREAKPOINTS.wide) return "comfortable";
|
|
382
|
+
return "wide";
|
|
383
|
+
}
|
|
352
384
|
|
|
353
385
|
// src/components/layout/header.tsx
|
|
354
386
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
@@ -553,12 +585,12 @@ function Footer() {
|
|
|
553
585
|
}
|
|
554
586
|
|
|
555
587
|
// src/hooks/use-container-size.ts
|
|
556
|
-
import { useEffect as
|
|
588
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
557
589
|
import { measureElement } from "ink";
|
|
558
590
|
function useContainerSize(ref) {
|
|
559
591
|
const terminal = useTerminalSize();
|
|
560
|
-
const [size, setSize] =
|
|
561
|
-
|
|
592
|
+
const [size, setSize] = useState2({ width: 0, height: 0 });
|
|
593
|
+
useEffect2(() => {
|
|
562
594
|
if (!ref.current) return;
|
|
563
595
|
const measured = measureElement(ref.current);
|
|
564
596
|
setSize(
|
|
@@ -835,7 +867,7 @@ async function markOnboardingComplete() {
|
|
|
835
867
|
}
|
|
836
868
|
|
|
837
869
|
// src/views/welcome.tsx
|
|
838
|
-
import { useEffect as
|
|
870
|
+
import { useEffect as useEffect3 } from "react";
|
|
839
871
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
840
872
|
|
|
841
873
|
// src/hooks/use-view-input.ts
|
|
@@ -849,7 +881,7 @@ function useViewInput(handler, opts) {
|
|
|
849
881
|
// src/views/welcome.tsx
|
|
850
882
|
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
851
883
|
function WelcomeView({ onContinue }) {
|
|
852
|
-
|
|
884
|
+
useEffect3(() => {
|
|
853
885
|
return () => {
|
|
854
886
|
};
|
|
855
887
|
}, []);
|
|
@@ -968,7 +1000,7 @@ function UpgradePrompt({ viewId }) {
|
|
|
968
1000
|
}
|
|
969
1001
|
|
|
970
1002
|
// src/views/dashboard.tsx
|
|
971
|
-
import { useEffect as
|
|
1003
|
+
import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
|
|
972
1004
|
import { Box as Box9, Text as Text12 } from "ink";
|
|
973
1005
|
|
|
974
1006
|
// src/hooks/use-visible-rows.ts
|
|
@@ -2071,10 +2103,6 @@ function formatDate(value) {
|
|
|
2071
2103
|
const locale = getLocale();
|
|
2072
2104
|
return date.toLocaleDateString(locale === "es" ? "es-ES" : "en-US");
|
|
2073
2105
|
}
|
|
2074
|
-
function truncate(str, maxLen) {
|
|
2075
|
-
if (str.length <= maxLen) return str;
|
|
2076
|
-
return str.slice(0, maxLen - 1) + "\u2026";
|
|
2077
|
-
}
|
|
2078
2106
|
|
|
2079
2107
|
// src/views/dashboard.tsx
|
|
2080
2108
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
@@ -2133,7 +2161,7 @@ function DashboardView() {
|
|
|
2133
2161
|
minRows: 2
|
|
2134
2162
|
});
|
|
2135
2163
|
const halfRows = Math.max(1, Math.floor(splitRows / 2));
|
|
2136
|
-
|
|
2164
|
+
useEffect4(() => {
|
|
2137
2165
|
fetchAll();
|
|
2138
2166
|
}, []);
|
|
2139
2167
|
useViewInput((input) => {
|
|
@@ -2246,14 +2274,14 @@ function DashboardView() {
|
|
|
2246
2274
|
}
|
|
2247
2275
|
|
|
2248
2276
|
// src/views/installed.tsx
|
|
2249
|
-
import { useState as
|
|
2277
|
+
import { useState as useState5, useMemo as useMemo3, useEffect as useEffect8, useRef as useRef3 } from "react";
|
|
2250
2278
|
import { Box as Box15, Text as Text18 } from "ink";
|
|
2251
2279
|
|
|
2252
2280
|
// src/hooks/use-debounce.ts
|
|
2253
|
-
import { useState as
|
|
2281
|
+
import { useState as useState3, useEffect as useEffect5 } from "react";
|
|
2254
2282
|
function useDebounce(value, delayMs) {
|
|
2255
|
-
const [debounced, setDebounced] =
|
|
2256
|
-
|
|
2283
|
+
const [debounced, setDebounced] = useState3(value);
|
|
2284
|
+
useEffect5(() => {
|
|
2257
2285
|
const timer = setTimeout(() => setDebounced(value), delayMs);
|
|
2258
2286
|
return () => clearTimeout(timer);
|
|
2259
2287
|
}, [value, delayMs]);
|
|
@@ -2261,7 +2289,7 @@ function useDebounce(value, delayMs) {
|
|
|
2261
2289
|
}
|
|
2262
2290
|
|
|
2263
2291
|
// src/hooks/use-brew-stream.ts
|
|
2264
|
-
import { useState as
|
|
2292
|
+
import { useState as useState4, useCallback, useRef as useRef2, useEffect as useEffect6 } from "react";
|
|
2265
2293
|
var MAX_LINES = 100;
|
|
2266
2294
|
async function logToHistory(args, success, error) {
|
|
2267
2295
|
const detected = detectAction(args);
|
|
@@ -2274,13 +2302,13 @@ async function logToHistory(args, success, error) {
|
|
|
2274
2302
|
}
|
|
2275
2303
|
}
|
|
2276
2304
|
function useBrewStream() {
|
|
2277
|
-
const [lines, setLines] =
|
|
2278
|
-
const [isRunning, setIsRunning] =
|
|
2279
|
-
const [error, setError2] =
|
|
2305
|
+
const [lines, setLines] = useState4([]);
|
|
2306
|
+
const [isRunning, setIsRunning] = useState4(false);
|
|
2307
|
+
const [error, setError2] = useState4(null);
|
|
2280
2308
|
const cancelRef = useRef2(false);
|
|
2281
2309
|
const generatorRef = useRef2(null);
|
|
2282
2310
|
const mountedRef = useRef2(true);
|
|
2283
|
-
|
|
2311
|
+
useEffect6(() => {
|
|
2284
2312
|
mountedRef.current = true;
|
|
2285
2313
|
return () => {
|
|
2286
2314
|
mountedRef.current = false;
|
|
@@ -2360,13 +2388,13 @@ function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
|
|
|
2360
2388
|
}
|
|
2361
2389
|
|
|
2362
2390
|
// src/components/common/confirm-dialog.tsx
|
|
2363
|
-
import { useEffect as
|
|
2391
|
+
import { useEffect as useEffect7 } from "react";
|
|
2364
2392
|
import { Box as Box11, Text as Text14, useInput as useInput3 } from "ink";
|
|
2365
2393
|
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2366
2394
|
function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
2367
2395
|
const locale = useLocaleStore((s) => s.locale);
|
|
2368
2396
|
const { openModal, closeModal } = useModalStore();
|
|
2369
|
-
|
|
2397
|
+
useEffect7(() => {
|
|
2370
2398
|
openModal();
|
|
2371
2399
|
return () => {
|
|
2372
2400
|
closeModal();
|
|
@@ -2450,14 +2478,18 @@ function InstalledView() {
|
|
|
2450
2478
|
const containerRef = useRef3(null);
|
|
2451
2479
|
const { width: containerWidth } = useContainerSize(containerRef);
|
|
2452
2480
|
const columns = containerWidth > 0 ? containerWidth : 80;
|
|
2453
|
-
const
|
|
2481
|
+
const mode = getLayoutMode(columns);
|
|
2482
|
+
const nameWidth = mode === "single" ? Math.max(
|
|
2483
|
+
8,
|
|
2484
|
+
columns - 2
|
|
2485
|
+
/* cursor + gap */
|
|
2486
|
+
) : Math.max(12, Math.floor(columns * 0.35));
|
|
2454
2487
|
const versionWidth = Math.max(8, Math.floor(columns * 0.15));
|
|
2455
|
-
const
|
|
2456
|
-
const [
|
|
2457
|
-
const [
|
|
2458
|
-
const [
|
|
2459
|
-
const [
|
|
2460
|
-
const [confirmUninstall, setConfirmUninstall] = useState6(null);
|
|
2488
|
+
const [filter, setFilter] = useState5("");
|
|
2489
|
+
const [cursor, setCursor] = useState5(0);
|
|
2490
|
+
const [tab, setTab] = useState5("formulae");
|
|
2491
|
+
const [isSearching, setIsSearching] = useState5(false);
|
|
2492
|
+
const [confirmUninstall, setConfirmUninstall] = useState5(null);
|
|
2461
2493
|
const debouncedFilter = useDebounce(filter, 200);
|
|
2462
2494
|
const stream = useBrewStream();
|
|
2463
2495
|
const listRows = useVisibleRows({
|
|
@@ -2470,10 +2502,10 @@ function InstalledView() {
|
|
|
2470
2502
|
fallbackReservedRows: 14,
|
|
2471
2503
|
minRows: 1
|
|
2472
2504
|
});
|
|
2473
|
-
|
|
2505
|
+
useEffect8(() => {
|
|
2474
2506
|
fetchInstalled();
|
|
2475
2507
|
}, []);
|
|
2476
|
-
|
|
2508
|
+
useEffect8(() => {
|
|
2477
2509
|
if (isSearching) {
|
|
2478
2510
|
openModal();
|
|
2479
2511
|
return () => {
|
|
@@ -2614,12 +2646,10 @@ function InstalledView() {
|
|
|
2614
2646
|
),
|
|
2615
2647
|
isSearching && /* @__PURE__ */ jsx19(Box15, { marginBottom: SPACING.xs, borderStyle: "round", borderColor: COLORS.gold, paddingX: SPACING.xs, children: /* @__PURE__ */ jsx19(SearchInput, { defaultValue: filter, onChange: setFilter, isActive: isSearching }) }),
|
|
2616
2648
|
/* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, children: [
|
|
2617
|
-
/* @__PURE__ */
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_version").padEnd(versionWidth) }),
|
|
2622
|
-
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_status") })
|
|
2649
|
+
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, children: " " }),
|
|
2650
|
+
/* @__PURE__ */ jsx19(Box15, { width: nameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, wrap: "truncate", children: t("installed_col_package") }) }),
|
|
2651
|
+
mode !== "single" && /* @__PURE__ */ jsx19(Box15, { width: versionWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, wrap: "truncate", children: t("installed_col_version") }) }),
|
|
2652
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsx19(Box15, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, wrap: "truncate", children: t("installed_col_status") }) })
|
|
2623
2653
|
] }),
|
|
2624
2654
|
/* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
|
|
2625
2655
|
visible.length === 0 && /* @__PURE__ */ jsx19(Box15, { paddingY: SPACING.xs, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, italic: true, children: t("installed_noPackages") }) }),
|
|
@@ -2630,14 +2660,25 @@ function InstalledView() {
|
|
|
2630
2660
|
visible.map((item, i) => {
|
|
2631
2661
|
const idx = start + i;
|
|
2632
2662
|
const isCurrent = idx === cursor;
|
|
2663
|
+
const hasBadge = item.outdated || item.pinned || item.kegOnly || item.installedAsDependency;
|
|
2633
2664
|
return /* @__PURE__ */ jsxs16(SelectableRow, { isCurrent, children: [
|
|
2634
|
-
/* @__PURE__ */ jsx19(
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2665
|
+
/* @__PURE__ */ jsx19(Box15, { width: nameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(
|
|
2666
|
+
Text18,
|
|
2667
|
+
{
|
|
2668
|
+
bold: isCurrent,
|
|
2669
|
+
inverse: isCurrent,
|
|
2670
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
2671
|
+
wrap: "truncate-middle",
|
|
2672
|
+
children: item.name
|
|
2673
|
+
}
|
|
2674
|
+
) }),
|
|
2675
|
+
mode !== "single" && /* @__PURE__ */ jsx19(Box15, { width: versionWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.teal, wrap: "truncate", children: item.version }) }),
|
|
2676
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsx19(Box15, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: hasBadge ? /* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, children: [
|
|
2677
|
+
item.outdated && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
|
|
2678
|
+
item.pinned && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
|
|
2679
|
+
item.kegOnly && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
|
|
2680
|
+
item.installedAsDependency && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_dep"), variant: "muted" })
|
|
2681
|
+
] }) : /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, dimColor: true, wrap: "truncate", children: item.desc }) })
|
|
2641
2682
|
] }, item.name);
|
|
2642
2683
|
}),
|
|
2643
2684
|
start + MAX_VISIBLE_ROWS < allItems.length && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -2650,17 +2691,17 @@ function InstalledView() {
|
|
|
2650
2691
|
}
|
|
2651
2692
|
|
|
2652
2693
|
// src/views/search.tsx
|
|
2653
|
-
import { useState as
|
|
2694
|
+
import { useState as useState6, useCallback as useCallback2, useEffect as useEffect9, useRef as useRef4 } from "react";
|
|
2654
2695
|
import { Box as Box16, Text as Text19 } from "ink";
|
|
2655
2696
|
import { TextInput as TextInput2 } from "@inkjs/ui";
|
|
2656
2697
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2657
2698
|
function SearchView() {
|
|
2658
|
-
const [query, setQuery] =
|
|
2659
|
-
const [results, setResults] =
|
|
2660
|
-
const [searching, setSearching] =
|
|
2661
|
-
const [searchError, setSearchError] =
|
|
2662
|
-
const [cursor, setCursor] =
|
|
2663
|
-
const [confirmInstall, setConfirmInstall] =
|
|
2699
|
+
const [query, setQuery] = useState6("");
|
|
2700
|
+
const [results, setResults] = useState6(null);
|
|
2701
|
+
const [searching, setSearching] = useState6(false);
|
|
2702
|
+
const [searchError, setSearchError] = useState6(null);
|
|
2703
|
+
const [cursor, setCursor] = useState6(0);
|
|
2704
|
+
const [confirmInstall, setConfirmInstall] = useState6(null);
|
|
2664
2705
|
const stream = useBrewStream();
|
|
2665
2706
|
const { openModal, closeModal } = useModalStore();
|
|
2666
2707
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
@@ -2677,7 +2718,7 @@ function SearchView() {
|
|
|
2677
2718
|
fallbackReservedRows: 14,
|
|
2678
2719
|
minRows: 1
|
|
2679
2720
|
});
|
|
2680
|
-
|
|
2721
|
+
useEffect9(() => {
|
|
2681
2722
|
if (results !== null) {
|
|
2682
2723
|
openModal();
|
|
2683
2724
|
return () => {
|
|
@@ -2705,7 +2746,7 @@ function SearchView() {
|
|
|
2705
2746
|
setSearching(false);
|
|
2706
2747
|
}
|
|
2707
2748
|
}, []);
|
|
2708
|
-
|
|
2749
|
+
useEffect9(() => {
|
|
2709
2750
|
if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
|
|
2710
2751
|
hasRefreshed.current = true;
|
|
2711
2752
|
void fetchInstalled();
|
|
@@ -2720,7 +2761,7 @@ function SearchView() {
|
|
|
2720
2761
|
Math.max(0, allResults.length - resultRows)
|
|
2721
2762
|
);
|
|
2722
2763
|
const visibleResults = allResults.slice(start, start + resultRows);
|
|
2723
|
-
|
|
2764
|
+
useEffect9(() => {
|
|
2724
2765
|
setCursor((current) => Math.min(current, Math.max(0, allResults.length - 1)));
|
|
2725
2766
|
}, [allResults.length]);
|
|
2726
2767
|
useViewInput((input, key) => {
|
|
@@ -2840,7 +2881,7 @@ function SearchView() {
|
|
|
2840
2881
|
const idx = start + i;
|
|
2841
2882
|
const isCurrent = idx === cursor;
|
|
2842
2883
|
return /* @__PURE__ */ jsxs17(SelectableRow, { isCurrent, children: [
|
|
2843
|
-
/* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, children: result.name }),
|
|
2884
|
+
/* @__PURE__ */ jsx20(Box16, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, wrap: "truncate-middle", children: result.name }) }),
|
|
2844
2885
|
/* @__PURE__ */ jsx20(
|
|
2845
2886
|
StatusBadge,
|
|
2846
2887
|
{
|
|
@@ -2862,7 +2903,7 @@ function SearchView() {
|
|
|
2862
2903
|
}
|
|
2863
2904
|
|
|
2864
2905
|
// src/views/outdated.tsx
|
|
2865
|
-
import { useEffect as
|
|
2906
|
+
import { useEffect as useEffect10, useMemo as useMemo4, useRef as useRef5, useState as useState7 } from "react";
|
|
2866
2907
|
import { Box as Box17, Text as Text20 } from "ink";
|
|
2867
2908
|
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2868
2909
|
function ImpactPanel({ impact }) {
|
|
@@ -2889,12 +2930,12 @@ function ImpactPanel({ impact }) {
|
|
|
2889
2930
|
function OutdatedView() {
|
|
2890
2931
|
const { outdated, loading, errors, fetchOutdated } = useBrewStore();
|
|
2891
2932
|
const stream = useBrewStream();
|
|
2892
|
-
const [cursor, setCursor] =
|
|
2893
|
-
const [confirmAction, setConfirmAction] =
|
|
2933
|
+
const [cursor, setCursor] = useState7(0);
|
|
2934
|
+
const [confirmAction, setConfirmAction] = useState7(null);
|
|
2894
2935
|
const hasRefreshed = useRef5(false);
|
|
2895
2936
|
const pendingUpgradeRef = useRef5(null);
|
|
2896
|
-
const [impact, setImpact] =
|
|
2897
|
-
const [impactLoading, setImpactLoading] =
|
|
2937
|
+
const [impact, setImpact] = useState7(null);
|
|
2938
|
+
const [impactLoading, setImpactLoading] = useState7(false);
|
|
2898
2939
|
const listRows = useVisibleRows({
|
|
2899
2940
|
reservedRows: impact || impactLoading ? 11 : 7,
|
|
2900
2941
|
fallbackReservedRows: impact || impactLoading ? 18 : 14,
|
|
@@ -2905,10 +2946,10 @@ function OutdatedView() {
|
|
|
2905
2946
|
fallbackReservedRows: 14,
|
|
2906
2947
|
minRows: 1
|
|
2907
2948
|
});
|
|
2908
|
-
|
|
2949
|
+
useEffect10(() => {
|
|
2909
2950
|
fetchOutdated();
|
|
2910
2951
|
}, []);
|
|
2911
|
-
|
|
2952
|
+
useEffect10(() => {
|
|
2912
2953
|
if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
|
|
2913
2954
|
hasRefreshed.current = true;
|
|
2914
2955
|
void fetchOutdated().then(() => {
|
|
@@ -2935,7 +2976,7 @@ function OutdatedView() {
|
|
|
2935
2976
|
[outdated.formulae, outdated.casks]
|
|
2936
2977
|
);
|
|
2937
2978
|
const debouncedCursor = useDebounce(cursor, 150);
|
|
2938
|
-
|
|
2979
|
+
useEffect10(() => {
|
|
2939
2980
|
const pkg = allOutdated[debouncedCursor];
|
|
2940
2981
|
if (!pkg || stream.isRunning) {
|
|
2941
2982
|
setImpact(null);
|
|
@@ -3061,7 +3102,16 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
3061
3102
|
const idx = start + i;
|
|
3062
3103
|
const isCurrent = idx === cursor;
|
|
3063
3104
|
return /* @__PURE__ */ jsxs18(SelectableRow, { isCurrent, children: [
|
|
3064
|
-
/* @__PURE__ */ jsx21(
|
|
3105
|
+
/* @__PURE__ */ jsx21(Box17, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx21(
|
|
3106
|
+
Text20,
|
|
3107
|
+
{
|
|
3108
|
+
bold: isCurrent,
|
|
3109
|
+
inverse: isCurrent,
|
|
3110
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
3111
|
+
wrap: "truncate-middle",
|
|
3112
|
+
children: pkg.name
|
|
3113
|
+
}
|
|
3114
|
+
) }),
|
|
3065
3115
|
/* @__PURE__ */ jsx21(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version }),
|
|
3066
3116
|
pkg.pinned && /* @__PURE__ */ jsx21(StatusBadge, { label: t("outdated_pinned"), variant: "info" })
|
|
3067
3117
|
] }, pkg.name);
|
|
@@ -3083,7 +3133,7 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
3083
3133
|
}
|
|
3084
3134
|
|
|
3085
3135
|
// src/views/package-info.tsx
|
|
3086
|
-
import { useEffect as
|
|
3136
|
+
import { useEffect as useEffect11, useRef as useRef6, useState as useState8 } from "react";
|
|
3087
3137
|
import { Box as Box18, Text as Text21 } from "ink";
|
|
3088
3138
|
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3089
3139
|
var ACTION_PROGRESS_KEYS = {
|
|
@@ -3099,21 +3149,21 @@ var ACTION_CONFIRM_KEYS = {
|
|
|
3099
3149
|
function PackageInfoView() {
|
|
3100
3150
|
const packageName = useNavigationStore((s) => s.selectedPackage);
|
|
3101
3151
|
const packageType = useNavigationStore((s) => s.selectedPackageType);
|
|
3102
|
-
const [formula, setFormula] =
|
|
3103
|
-
const [loading, setLoading2] =
|
|
3104
|
-
const [error, setError2] =
|
|
3105
|
-
const [confirmAction, setConfirmAction] =
|
|
3152
|
+
const [formula, setFormula] = useState8(null);
|
|
3153
|
+
const [loading, setLoading2] = useState8(true);
|
|
3154
|
+
const [error, setError2] = useState8(null);
|
|
3155
|
+
const [confirmAction, setConfirmAction] = useState8(null);
|
|
3106
3156
|
const activeActionRef = useRef6("install");
|
|
3107
3157
|
const mountedRef = useRef6(true);
|
|
3108
3158
|
const hasRefreshed = useRef6(false);
|
|
3109
3159
|
const stream = useBrewStream();
|
|
3110
|
-
|
|
3160
|
+
useEffect11(() => {
|
|
3111
3161
|
mountedRef.current = true;
|
|
3112
3162
|
return () => {
|
|
3113
3163
|
mountedRef.current = false;
|
|
3114
3164
|
};
|
|
3115
3165
|
}, []);
|
|
3116
|
-
|
|
3166
|
+
useEffect11(() => {
|
|
3117
3167
|
if (!packageName) return;
|
|
3118
3168
|
setLoading2(true);
|
|
3119
3169
|
const fetchInfo = async () => {
|
|
@@ -3138,7 +3188,7 @@ function PackageInfoView() {
|
|
|
3138
3188
|
}
|
|
3139
3189
|
});
|
|
3140
3190
|
}, [packageName, packageType]);
|
|
3141
|
-
|
|
3191
|
+
useEffect11(() => {
|
|
3142
3192
|
if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current && packageName) {
|
|
3143
3193
|
hasRefreshed.current = true;
|
|
3144
3194
|
const refreshFn = packageType === "cask" ? getCaskInfo(packageName).then((c) => c ? { ...c, installed: c.installed ? [{ version: c.installed }] : [] } : null) : getFormulaInfo(packageName);
|
|
@@ -3298,7 +3348,7 @@ function PackageInfoView() {
|
|
|
3298
3348
|
}
|
|
3299
3349
|
|
|
3300
3350
|
// src/views/services.tsx
|
|
3301
|
-
import { useEffect as
|
|
3351
|
+
import { useEffect as useEffect12, useRef as useRef7, useState as useState9 } from "react";
|
|
3302
3352
|
import { Box as Box19, Text as Text22 } from "ink";
|
|
3303
3353
|
import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3304
3354
|
var STATUS_VARIANTS = {
|
|
@@ -3315,21 +3365,26 @@ function humaniseServiceError(message) {
|
|
|
3315
3365
|
}
|
|
3316
3366
|
function ServicesView() {
|
|
3317
3367
|
const { services, loading, errors, fetchServices, serviceAction: serviceAction2 } = useBrewStore();
|
|
3318
|
-
const [cursor, setCursor] =
|
|
3319
|
-
const [actionInProgress, setActionInProgress] =
|
|
3320
|
-
const [confirmAction, setConfirmAction] =
|
|
3321
|
-
const [lastError, setLastError] =
|
|
3368
|
+
const [cursor, setCursor] = useState9(0);
|
|
3369
|
+
const [actionInProgress, setActionInProgress] = useState9(false);
|
|
3370
|
+
const [confirmAction, setConfirmAction] = useState9(null);
|
|
3371
|
+
const [lastError, setLastError] = useState9(null);
|
|
3322
3372
|
const containerRef = useRef7(null);
|
|
3323
3373
|
const { width: containerWidth } = useContainerSize(containerRef);
|
|
3324
3374
|
const cols = containerWidth > 0 ? containerWidth : 80;
|
|
3325
|
-
const
|
|
3375
|
+
const mode = getLayoutMode(cols);
|
|
3376
|
+
const svcNameWidth = mode === "single" ? Math.max(
|
|
3377
|
+
8,
|
|
3378
|
+
cols - 2
|
|
3379
|
+
/* cursor + gap */
|
|
3380
|
+
) : Math.max(12, Math.floor(cols * 0.35));
|
|
3326
3381
|
const svcStatusWidth = Math.max(8, Math.floor(cols * 0.15));
|
|
3327
3382
|
const MAX_VISIBLE_ROWS = useVisibleRows({
|
|
3328
3383
|
reservedRows: lastError || actionInProgress ? 8 : 6,
|
|
3329
3384
|
fallbackReservedRows: lastError || actionInProgress ? 16 : 14,
|
|
3330
3385
|
minRows: 1
|
|
3331
3386
|
});
|
|
3332
|
-
|
|
3387
|
+
useEffect12(() => {
|
|
3333
3388
|
fetchServices();
|
|
3334
3389
|
}, []);
|
|
3335
3390
|
useViewInput((input, key) => {
|
|
@@ -3394,12 +3449,10 @@ function ServicesView() {
|
|
|
3394
3449
|
) }),
|
|
3395
3450
|
/* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
3396
3451
|
/* @__PURE__ */ jsxs20(Box19, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, paddingBottom: SPACING.none, children: [
|
|
3397
|
-
/* @__PURE__ */
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_status").padEnd(svcStatusWidth) }),
|
|
3402
|
-
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_user") })
|
|
3452
|
+
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: " " }),
|
|
3453
|
+
/* @__PURE__ */ jsx23(Box19, { width: svcNameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, wrap: "truncate", children: t("services_name") }) }),
|
|
3454
|
+
mode !== "single" && /* @__PURE__ */ jsx23(Box19, { width: svcStatusWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, wrap: "truncate", children: t("services_status") }) }),
|
|
3455
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsx23(Box19, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, wrap: "truncate", children: t("services_user") }) })
|
|
3403
3456
|
] }),
|
|
3404
3457
|
start > 0 && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3405
3458
|
" ",
|
|
@@ -3409,10 +3462,21 @@ function ServicesView() {
|
|
|
3409
3462
|
const idx = start + i;
|
|
3410
3463
|
const isCurrent = idx === cursor;
|
|
3411
3464
|
return /* @__PURE__ */ jsxs20(SelectableRow, { isCurrent, children: [
|
|
3412
|
-
/* @__PURE__ */ jsx23(
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3465
|
+
/* @__PURE__ */ jsx23(Box19, { width: svcNameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(
|
|
3466
|
+
Text22,
|
|
3467
|
+
{
|
|
3468
|
+
bold: isCurrent,
|
|
3469
|
+
inverse: isCurrent,
|
|
3470
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
3471
|
+
wrap: "truncate-middle",
|
|
3472
|
+
children: svc.name
|
|
3473
|
+
}
|
|
3474
|
+
) }),
|
|
3475
|
+
mode !== "single" && /* @__PURE__ */ jsx23(Box19, { width: svcStatusWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(StatusBadge, { label: svc.status, variant: STATUS_VARIANTS[svc.status] }) }),
|
|
3476
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsxs20(Box19, { flexGrow: 1, flexShrink: 1, minWidth: 0, gap: SPACING.xs, children: [
|
|
3477
|
+
/* @__PURE__ */ jsx23(Text22, { color: COLORS.muted, wrap: "truncate", children: svc.user ?? "-" }),
|
|
3478
|
+
svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: t("common_exit", { code: svc.exit_code }) })
|
|
3479
|
+
] })
|
|
3416
3480
|
] }, svc.name);
|
|
3417
3481
|
}),
|
|
3418
3482
|
start + MAX_VISIBLE_ROWS < services.length && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -3431,25 +3495,25 @@ function ServicesView() {
|
|
|
3431
3495
|
}
|
|
3432
3496
|
|
|
3433
3497
|
// src/views/doctor.tsx
|
|
3434
|
-
import { useEffect as
|
|
3498
|
+
import { useEffect as useEffect13, useRef as useRef8, useState as useState10 } from "react";
|
|
3435
3499
|
import { Box as Box20, Text as Text23 } from "ink";
|
|
3436
3500
|
import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3437
3501
|
function DoctorView() {
|
|
3438
3502
|
const { doctorWarnings, doctorClean, loading, errors, fetchDoctor } = useBrewStore();
|
|
3439
|
-
const [cursor, setCursor] =
|
|
3503
|
+
const [cursor, setCursor] = useState10(0);
|
|
3440
3504
|
const visibleWarnings = useVisibleRows({
|
|
3441
3505
|
reservedRows: 6,
|
|
3442
3506
|
fallbackReservedRows: 14,
|
|
3443
3507
|
minRows: 1
|
|
3444
3508
|
});
|
|
3445
3509
|
const mountedRef = useRef8(true);
|
|
3446
|
-
|
|
3510
|
+
useEffect13(() => {
|
|
3447
3511
|
mountedRef.current = true;
|
|
3448
3512
|
return () => {
|
|
3449
3513
|
mountedRef.current = false;
|
|
3450
3514
|
};
|
|
3451
3515
|
}, []);
|
|
3452
|
-
|
|
3516
|
+
useEffect13(() => {
|
|
3453
3517
|
fetchDoctor();
|
|
3454
3518
|
}, []);
|
|
3455
3519
|
useViewInput((input, key) => {
|
|
@@ -3487,7 +3551,7 @@ function DoctorView() {
|
|
|
3487
3551
|
}
|
|
3488
3552
|
|
|
3489
3553
|
// src/views/profiles.tsx
|
|
3490
|
-
import { useEffect as
|
|
3554
|
+
import { useEffect as useEffect14, useRef as useRef9, useState as useState11 } from "react";
|
|
3491
3555
|
import { Box as Box25 } from "ink";
|
|
3492
3556
|
|
|
3493
3557
|
// src/stores/profile-store.ts
|
|
@@ -3859,23 +3923,23 @@ function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
|
|
|
3859
3923
|
import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3860
3924
|
function ProfilesView() {
|
|
3861
3925
|
const { profileNames, selectedProfile, loading, loadError, fetchProfiles, loadProfile: loadProfile2, exportCurrent, deleteProfile: deleteProfile2, updateProfile: updateProfile2 } = useProfileStore();
|
|
3862
|
-
const [cursor, setCursor] =
|
|
3863
|
-
const [mode, setMode] =
|
|
3864
|
-
const [newName, setNewName] =
|
|
3865
|
-
const [confirmDelete, setConfirmDelete] =
|
|
3866
|
-
const [editName, setEditName] =
|
|
3867
|
-
const [editDesc, setEditDesc] =
|
|
3868
|
-
const [importLines, setImportLines] =
|
|
3869
|
-
const [importRunning, setImportRunning] =
|
|
3870
|
-
const [importHadError, setImportHadError] =
|
|
3871
|
-
const [importProfile2, setImportProfile] =
|
|
3926
|
+
const [cursor, setCursor] = useState11(0);
|
|
3927
|
+
const [mode, setMode] = useState11("list");
|
|
3928
|
+
const [newName, setNewName] = useState11("");
|
|
3929
|
+
const [confirmDelete, setConfirmDelete] = useState11(false);
|
|
3930
|
+
const [editName, setEditName] = useState11("");
|
|
3931
|
+
const [editDesc, setEditDesc] = useState11("");
|
|
3932
|
+
const [importLines, setImportLines] = useState11([]);
|
|
3933
|
+
const [importRunning, setImportRunning] = useState11(false);
|
|
3934
|
+
const [importHadError, setImportHadError] = useState11(false);
|
|
3935
|
+
const [importProfile2, setImportProfile] = useState11(null);
|
|
3872
3936
|
const { openModal, closeModal } = useModalStore();
|
|
3873
3937
|
const importGenRef = useRef9(null);
|
|
3874
3938
|
const mountedRef = useRef9(true);
|
|
3875
|
-
|
|
3939
|
+
useEffect14(() => {
|
|
3876
3940
|
fetchProfiles();
|
|
3877
3941
|
}, []);
|
|
3878
|
-
|
|
3942
|
+
useEffect14(() => {
|
|
3879
3943
|
mountedRef.current = true;
|
|
3880
3944
|
return () => {
|
|
3881
3945
|
mountedRef.current = false;
|
|
@@ -3883,7 +3947,7 @@ function ProfilesView() {
|
|
|
3883
3947
|
importGenRef.current = null;
|
|
3884
3948
|
};
|
|
3885
3949
|
}, []);
|
|
3886
|
-
|
|
3950
|
+
useEffect14(() => {
|
|
3887
3951
|
if (mode !== "list") {
|
|
3888
3952
|
openModal();
|
|
3889
3953
|
return () => {
|
|
@@ -4059,7 +4123,7 @@ function ProfilesView() {
|
|
|
4059
4123
|
}
|
|
4060
4124
|
|
|
4061
4125
|
// src/views/smart-cleanup.tsx
|
|
4062
|
-
import { useEffect as
|
|
4126
|
+
import { useEffect as useEffect15, useRef as useRef10, useState as useState12 } from "react";
|
|
4063
4127
|
import { Box as Box26, Text as Text28 } from "ink";
|
|
4064
4128
|
|
|
4065
4129
|
// src/stores/cleanup-store.ts
|
|
@@ -4183,10 +4247,10 @@ var useCleanupStore = create10((set, get) => ({
|
|
|
4183
4247
|
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4184
4248
|
function SmartCleanupView() {
|
|
4185
4249
|
const { summary, selected, loading, error, analyze, toggleSelect, selectAll } = useCleanupStore();
|
|
4186
|
-
const [cursor, setCursor] =
|
|
4187
|
-
const [confirmClean, setConfirmClean] =
|
|
4188
|
-
const [confirmForce, setConfirmForce] =
|
|
4189
|
-
const [failedNames, setFailedNames] =
|
|
4250
|
+
const [cursor, setCursor] = useState12(0);
|
|
4251
|
+
const [confirmClean, setConfirmClean] = useState12(false);
|
|
4252
|
+
const [confirmForce, setConfirmForce] = useState12(false);
|
|
4253
|
+
const [failedNames, setFailedNames] = useState12([]);
|
|
4190
4254
|
const stream = useBrewStream();
|
|
4191
4255
|
const hasRefreshed = useRef10(false);
|
|
4192
4256
|
const listRows = useVisibleRows({
|
|
@@ -4194,10 +4258,10 @@ function SmartCleanupView() {
|
|
|
4194
4258
|
fallbackReservedRows: confirmClean || confirmForce ? 18 : 14,
|
|
4195
4259
|
minRows: 1
|
|
4196
4260
|
});
|
|
4197
|
-
|
|
4261
|
+
useEffect15(() => {
|
|
4198
4262
|
analyze();
|
|
4199
4263
|
}, []);
|
|
4200
|
-
|
|
4264
|
+
useEffect15(() => {
|
|
4201
4265
|
if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
|
|
4202
4266
|
hasRefreshed.current = true;
|
|
4203
4267
|
void analyze();
|
|
@@ -4333,7 +4397,7 @@ function SmartCleanupView() {
|
|
|
4333
4397
|
}
|
|
4334
4398
|
|
|
4335
4399
|
// src/views/history.tsx
|
|
4336
|
-
import { useEffect as
|
|
4400
|
+
import { useEffect as useEffect16, useState as useState13, useMemo as useMemo5 } from "react";
|
|
4337
4401
|
import { Box as Box27, Text as Text29 } from "ink";
|
|
4338
4402
|
|
|
4339
4403
|
// src/stores/history-store.ts
|
|
@@ -4386,12 +4450,12 @@ var ACTION_LABEL_KEYS = {
|
|
|
4386
4450
|
var FILTERS = ["all", "install", "uninstall", "upgrade", "upgrade-all"];
|
|
4387
4451
|
function HistoryView() {
|
|
4388
4452
|
const { entries, loading, error, fetchHistory, clearHistory: clearHistory2 } = useHistoryStore();
|
|
4389
|
-
const [cursor, setCursor] =
|
|
4390
|
-
const [filter, setFilter] =
|
|
4391
|
-
const [searchQuery, setSearchQuery] =
|
|
4392
|
-
const [isSearching, setIsSearching] =
|
|
4393
|
-
const [confirmClear, setConfirmClear] =
|
|
4394
|
-
const [confirmReplay, setConfirmReplay] =
|
|
4453
|
+
const [cursor, setCursor] = useState13(0);
|
|
4454
|
+
const [filter, setFilter] = useState13("all");
|
|
4455
|
+
const [searchQuery, setSearchQuery] = useState13("");
|
|
4456
|
+
const [isSearching, setIsSearching] = useState13(false);
|
|
4457
|
+
const [confirmClear, setConfirmClear] = useState13(false);
|
|
4458
|
+
const [confirmReplay, setConfirmReplay] = useState13(null);
|
|
4395
4459
|
const stream = useBrewStream();
|
|
4396
4460
|
const debouncedQuery = useDebounce(searchQuery, 200);
|
|
4397
4461
|
const { openModal, closeModal } = useModalStore();
|
|
@@ -4405,10 +4469,10 @@ function HistoryView() {
|
|
|
4405
4469
|
fallbackReservedRows: 16,
|
|
4406
4470
|
minRows: 1
|
|
4407
4471
|
});
|
|
4408
|
-
|
|
4472
|
+
useEffect16(() => {
|
|
4409
4473
|
fetchHistory();
|
|
4410
4474
|
}, []);
|
|
4411
|
-
|
|
4475
|
+
useEffect16(() => {
|
|
4412
4476
|
if (isSearching) {
|
|
4413
4477
|
openModal();
|
|
4414
4478
|
return () => {
|
|
@@ -4529,8 +4593,8 @@ function HistoryView() {
|
|
|
4529
4593
|
const ts = new Date(entry.timestamp).getTime() / 1e3;
|
|
4530
4594
|
return /* @__PURE__ */ jsxs28(SelectableRow, { isCurrent, children: [
|
|
4531
4595
|
/* @__PURE__ */ jsx31(Text29, { color, bold: true, children: icon }),
|
|
4532
|
-
/* @__PURE__ */ jsx31(Text29, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: t(ACTION_LABEL_KEYS[entry.action])
|
|
4533
|
-
/* @__PURE__ */ jsx31(Text29, { color: COLORS.text, children: entry.packageName ?? t("history_all") }),
|
|
4596
|
+
/* @__PURE__ */ jsx31(Box27, { width: 14, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx31(Text29, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, wrap: "truncate", children: t(ACTION_LABEL_KEYS[entry.action]) }) }),
|
|
4597
|
+
/* @__PURE__ */ jsx31(Box27, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx31(Text29, { color: COLORS.text, wrap: "truncate-middle", children: entry.packageName ?? t("history_all") }) }),
|
|
4534
4598
|
entry.success ? /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_ok"), variant: "success" }) : /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_fail"), variant: "error" }),
|
|
4535
4599
|
/* @__PURE__ */ jsx31(Text29, { color: COLORS.muted, children: formatRelativeTime(ts) })
|
|
4536
4600
|
] }, entry.id);
|
|
@@ -4549,7 +4613,7 @@ function HistoryView() {
|
|
|
4549
4613
|
}
|
|
4550
4614
|
|
|
4551
4615
|
// src/views/security-audit.tsx
|
|
4552
|
-
import { useEffect as
|
|
4616
|
+
import { useEffect as useEffect17, useState as useState14 } from "react";
|
|
4553
4617
|
import { Box as Box28, Text as Text30 } from "ink";
|
|
4554
4618
|
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4555
4619
|
var SEVERITY_COLORS = {
|
|
@@ -4572,11 +4636,11 @@ function isNetworkError(msg) {
|
|
|
4572
4636
|
function SecurityAuditView() {
|
|
4573
4637
|
const { summary, loading, error, scan, cachedAt } = useSecurityStore();
|
|
4574
4638
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
4575
|
-
const [cursor, setCursor] =
|
|
4576
|
-
const [expandedPkg, setExpandedPkg] =
|
|
4577
|
-
const [confirmUpgrade, setConfirmUpgrade] =
|
|
4639
|
+
const [cursor, setCursor] = useState14(0);
|
|
4640
|
+
const [expandedPkg, setExpandedPkg] = useState14(null);
|
|
4641
|
+
const [confirmUpgrade, setConfirmUpgrade] = useState14(null);
|
|
4578
4642
|
const stream = useBrewStream();
|
|
4579
|
-
|
|
4643
|
+
useEffect17(() => {
|
|
4580
4644
|
scan();
|
|
4581
4645
|
}, []);
|
|
4582
4646
|
const results = summary?.results ?? [];
|
|
@@ -4681,7 +4745,7 @@ function SecurityAuditView() {
|
|
|
4681
4745
|
}
|
|
4682
4746
|
|
|
4683
4747
|
// src/views/account.tsx
|
|
4684
|
-
import { useState as
|
|
4748
|
+
import { useState as useState15 } from "react";
|
|
4685
4749
|
import { Box as Box29, Text as Text31 } from "ink";
|
|
4686
4750
|
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4687
4751
|
|
|
@@ -4763,13 +4827,13 @@ async function redeemPromoCode(code) {
|
|
|
4763
4827
|
import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4764
4828
|
function AccountView() {
|
|
4765
4829
|
const { status, license, deactivate: deactivate2, revalidate: revalidate2, degradation } = useLicenseStore();
|
|
4766
|
-
const [confirmDeactivate, setConfirmDeactivate] =
|
|
4767
|
-
const [deactivating, setDeactivating] =
|
|
4768
|
-
const [deactivateError, setDeactivateError] =
|
|
4769
|
-
const [promoMode, setPromoMode] =
|
|
4770
|
-
const [promoLoading, setPromoLoading] =
|
|
4771
|
-
const [promoResult, setPromoResult] =
|
|
4772
|
-
const [revalidating, setRevalidating] =
|
|
4830
|
+
const [confirmDeactivate, setConfirmDeactivate] = useState15(false);
|
|
4831
|
+
const [deactivating, setDeactivating] = useState15(false);
|
|
4832
|
+
const [deactivateError, setDeactivateError] = useState15(null);
|
|
4833
|
+
const [promoMode, setPromoMode] = useState15(false);
|
|
4834
|
+
const [promoLoading, setPromoLoading] = useState15(false);
|
|
4835
|
+
const [promoResult, setPromoResult] = useState15(null);
|
|
4836
|
+
const [revalidating, setRevalidating] = useState15(false);
|
|
4773
4837
|
useViewInput((input, key) => {
|
|
4774
4838
|
if (confirmDeactivate || deactivating || promoMode || revalidating) {
|
|
4775
4839
|
if (key.escape && promoMode) {
|
|
@@ -4913,13 +4977,13 @@ function AccountView() {
|
|
|
4913
4977
|
status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
|
|
4914
4978
|
revalidating ? t("account_revalidating") : "",
|
|
4915
4979
|
" ",
|
|
4916
|
-
t("app_version", { version: "1.1
|
|
4980
|
+
t("app_version", { version: "1.2.1" })
|
|
4917
4981
|
] }) })
|
|
4918
4982
|
] });
|
|
4919
4983
|
}
|
|
4920
4984
|
|
|
4921
4985
|
// src/views/rollback.tsx
|
|
4922
|
-
import { useCallback as useCallback3, useEffect as
|
|
4986
|
+
import { useCallback as useCallback3, useEffect as useEffect18, useRef as useRef11, useState as useState16 } from "react";
|
|
4923
4987
|
import { Box as Box30, Text as Text32 } from "ink";
|
|
4924
4988
|
|
|
4925
4989
|
// src/stores/rollback-store.ts
|
|
@@ -4955,10 +5019,10 @@ async function detectStrategy(name, targetVersion, packageType) {
|
|
|
4955
5019
|
}
|
|
4956
5020
|
return { strategy: "pin-only" };
|
|
4957
5021
|
}
|
|
4958
|
-
async function buildRollbackPlan(
|
|
5022
|
+
async function buildRollbackPlan(snapshot2, isPro) {
|
|
4959
5023
|
if (!isPro) throw new Error("Pro license required");
|
|
4960
5024
|
const current = await captureSnapshot();
|
|
4961
|
-
const diff = diffSnapshots(
|
|
5025
|
+
const diff = diffSnapshots(snapshot2, current);
|
|
4962
5026
|
const actions = [];
|
|
4963
5027
|
const warnings = [];
|
|
4964
5028
|
for (const entry of diff.upgraded) {
|
|
@@ -5024,8 +5088,8 @@ async function buildRollbackPlan(snapshot, isPro) {
|
|
|
5024
5088
|
warnings.push(`${caskPinCount} cask(s) will be pinned only (version restoration not supported)`);
|
|
5025
5089
|
}
|
|
5026
5090
|
const canExecute = actions.some((a) => a.strategy !== "unavailable");
|
|
5027
|
-
const snapshotLabel =
|
|
5028
|
-
const snapshotDate = new Date(
|
|
5091
|
+
const snapshotLabel = snapshot2.label ?? "Auto";
|
|
5092
|
+
const snapshotDate = new Date(snapshot2.capturedAt).toLocaleString();
|
|
5029
5093
|
logger.debug("Built rollback plan", { actionCount: actions.length, canExecute });
|
|
5030
5094
|
return {
|
|
5031
5095
|
snapshotLabel,
|
|
@@ -5113,14 +5177,14 @@ var useRollbackStore = create12((set) => ({
|
|
|
5113
5177
|
set({ error: err instanceof Error ? err.message : String(err), loading: false });
|
|
5114
5178
|
}
|
|
5115
5179
|
},
|
|
5116
|
-
selectSnapshot: async (
|
|
5117
|
-
if (!
|
|
5180
|
+
selectSnapshot: async (snapshot2, isPro) => {
|
|
5181
|
+
if (!snapshot2) {
|
|
5118
5182
|
set({ selectedSnapshot: null, plan: null, planError: null });
|
|
5119
5183
|
return;
|
|
5120
5184
|
}
|
|
5121
|
-
set({ selectedSnapshot:
|
|
5185
|
+
set({ selectedSnapshot: snapshot2, plan: null, planLoading: true, planError: null });
|
|
5122
5186
|
try {
|
|
5123
|
-
const plan = await buildRollbackPlan(
|
|
5187
|
+
const plan = await buildRollbackPlan(snapshot2, isPro);
|
|
5124
5188
|
set({ plan, planLoading: false });
|
|
5125
5189
|
} catch (err) {
|
|
5126
5190
|
set({ planError: err instanceof Error ? err.message : String(err), planLoading: false });
|
|
@@ -5225,11 +5289,11 @@ function PlanView({ plan }) {
|
|
|
5225
5289
|
function RollbackView() {
|
|
5226
5290
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5227
5291
|
const { snapshots, loading, error, plan, planLoading, planError, fetchSnapshots, selectSnapshot, clearPlan } = useRollbackStore();
|
|
5228
|
-
const [cursor, setCursor] =
|
|
5229
|
-
const [phase, setPhase] =
|
|
5230
|
-
const [streamLines, setStreamLines] =
|
|
5231
|
-
const [streamRunning, setStreamRunning] =
|
|
5232
|
-
const [streamError, setStreamError] =
|
|
5292
|
+
const [cursor, setCursor] = useState16(0);
|
|
5293
|
+
const [phase, setPhase] = useState16("list");
|
|
5294
|
+
const [streamLines, setStreamLines] = useState16([]);
|
|
5295
|
+
const [streamRunning, setStreamRunning] = useState16(false);
|
|
5296
|
+
const [streamError, setStreamError] = useState16(null);
|
|
5233
5297
|
const generatorRef = useRef11(null);
|
|
5234
5298
|
const mountedRef = useRef11(true);
|
|
5235
5299
|
const snapshotRows = useVisibleRows({
|
|
@@ -5237,14 +5301,14 @@ function RollbackView() {
|
|
|
5237
5301
|
fallbackReservedRows: 14,
|
|
5238
5302
|
minRows: 1
|
|
5239
5303
|
});
|
|
5240
|
-
|
|
5304
|
+
useEffect18(() => {
|
|
5241
5305
|
mountedRef.current = true;
|
|
5242
5306
|
return () => {
|
|
5243
5307
|
mountedRef.current = false;
|
|
5244
5308
|
void generatorRef.current?.return(void 0);
|
|
5245
5309
|
};
|
|
5246
5310
|
}, []);
|
|
5247
|
-
|
|
5311
|
+
useEffect18(() => {
|
|
5248
5312
|
void fetchSnapshots(isPro());
|
|
5249
5313
|
}, []);
|
|
5250
5314
|
const runRollback = useCallback3(async (p) => {
|
|
@@ -5381,7 +5445,7 @@ function RollbackView() {
|
|
|
5381
5445
|
}
|
|
5382
5446
|
|
|
5383
5447
|
// src/views/brewfile.tsx
|
|
5384
|
-
import { useCallback as useCallback4, useEffect as
|
|
5448
|
+
import { useCallback as useCallback4, useEffect as useEffect19, useRef as useRef12, useState as useState17 } from "react";
|
|
5385
5449
|
import { Box as Box31, Text as Text33 } from "ink";
|
|
5386
5450
|
import { TextInput as TextInput6 } from "@inkjs/ui";
|
|
5387
5451
|
import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
@@ -5427,14 +5491,14 @@ function DriftSummary({ drift }) {
|
|
|
5427
5491
|
function BrewfileView() {
|
|
5428
5492
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5429
5493
|
const { schema, drift, loading, driftLoading, error, load, createFromCurrent } = useBrewfileStore();
|
|
5430
|
-
const [phase, setPhase] =
|
|
5431
|
-
const [streamLines, setStreamLines] =
|
|
5432
|
-
const [streamRunning, setStreamRunning] =
|
|
5433
|
-
const [streamError, setStreamError] =
|
|
5434
|
-
const [resultMessage, setResultMessage] =
|
|
5494
|
+
const [phase, setPhase] = useState17("overview");
|
|
5495
|
+
const [streamLines, setStreamLines] = useState17([]);
|
|
5496
|
+
const [streamRunning, setStreamRunning] = useState17(false);
|
|
5497
|
+
const [streamError, setStreamError] = useState17(null);
|
|
5498
|
+
const [resultMessage, setResultMessage] = useState17("");
|
|
5435
5499
|
const generatorRef = useRef12(null);
|
|
5436
5500
|
const mountedRef = useRef12(true);
|
|
5437
|
-
|
|
5501
|
+
useEffect19(() => {
|
|
5438
5502
|
mountedRef.current = true;
|
|
5439
5503
|
void load();
|
|
5440
5504
|
return () => {
|
|
@@ -5610,7 +5674,7 @@ function BrewfileView() {
|
|
|
5610
5674
|
}
|
|
5611
5675
|
|
|
5612
5676
|
// src/views/sync.tsx
|
|
5613
|
-
import { useCallback as useCallback5, useEffect as
|
|
5677
|
+
import { useCallback as useCallback5, useEffect as useEffect20, useState as useState18 } from "react";
|
|
5614
5678
|
import { Box as Box32, Text as Text34 } from "ink";
|
|
5615
5679
|
import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5616
5680
|
function OverviewSection({
|
|
@@ -5736,14 +5800,14 @@ function SyncView() {
|
|
|
5736
5800
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5737
5801
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
5738
5802
|
const { config, lastResult, conflicts, loading, error, initialize, syncNow, resolveConflicts } = useSyncStore();
|
|
5739
|
-
const [phase, setPhase] =
|
|
5740
|
-
const [syncError, setSyncError] =
|
|
5741
|
-
const [conflictEntries, setConflictEntries] =
|
|
5742
|
-
const [cursor, setCursor] =
|
|
5743
|
-
|
|
5803
|
+
const [phase, setPhase] = useState18("overview");
|
|
5804
|
+
const [syncError, setSyncError] = useState18(null);
|
|
5805
|
+
const [conflictEntries, setConflictEntries] = useState18([]);
|
|
5806
|
+
const [cursor, setCursor] = useState18(0);
|
|
5807
|
+
useEffect20(() => {
|
|
5744
5808
|
void initialize(isPro());
|
|
5745
5809
|
}, []);
|
|
5746
|
-
|
|
5810
|
+
useEffect20(() => {
|
|
5747
5811
|
if (conflicts.length > 0) {
|
|
5748
5812
|
setConflictEntries(
|
|
5749
5813
|
conflicts.map((c) => ({ conflict: c, resolution: "pending" }))
|
|
@@ -5908,7 +5972,7 @@ function SyncView() {
|
|
|
5908
5972
|
}
|
|
5909
5973
|
|
|
5910
5974
|
// src/views/compliance.tsx
|
|
5911
|
-
import { useCallback as useCallback6, useEffect as
|
|
5975
|
+
import { useCallback as useCallback6, useEffect as useEffect21, useRef as useRef13, useState as useState19 } from "react";
|
|
5912
5976
|
import { Box as Box33, Text as Text35 } from "ink";
|
|
5913
5977
|
import { TextInput as TextInput7 } from "@inkjs/ui";
|
|
5914
5978
|
|
|
@@ -6035,13 +6099,13 @@ function ViolationList({ violations }) {
|
|
|
6035
6099
|
function ComplianceView() {
|
|
6036
6100
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
6037
6101
|
const { policy, report, loading, error, importPolicy, runCheck } = useComplianceStore();
|
|
6038
|
-
const [phase, setPhase] =
|
|
6039
|
-
const [resultMessage, setResultMessage] =
|
|
6040
|
-
const [streamLines, setStreamLines] =
|
|
6041
|
-
const [streamRunning, setStreamRunning] =
|
|
6102
|
+
const [phase, setPhase] = useState19("overview");
|
|
6103
|
+
const [resultMessage, setResultMessage] = useState19(null);
|
|
6104
|
+
const [streamLines, setStreamLines] = useState19([]);
|
|
6105
|
+
const [streamRunning, setStreamRunning] = useState19(false);
|
|
6042
6106
|
const generatorRef = useRef13(null);
|
|
6043
6107
|
const mountedRef = useRef13(true);
|
|
6044
|
-
|
|
6108
|
+
useEffect21(() => {
|
|
6045
6109
|
mountedRef.current = true;
|
|
6046
6110
|
return () => {
|
|
6047
6111
|
mountedRef.current = false;
|
|
@@ -6246,7 +6310,7 @@ function ComplianceView() {
|
|
|
6246
6310
|
import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6247
6311
|
function LicenseInitializer() {
|
|
6248
6312
|
const initLicense = useLicenseStore((s) => s.initialize);
|
|
6249
|
-
|
|
6313
|
+
useEffect22(() => {
|
|
6250
6314
|
initLicense();
|
|
6251
6315
|
}, []);
|
|
6252
6316
|
return null;
|
|
@@ -6299,8 +6363,8 @@ function App() {
|
|
|
6299
6363
|
const { exit } = useApp();
|
|
6300
6364
|
const currentView = useNavigationStore((s) => s.currentView);
|
|
6301
6365
|
const isTestEnv = typeof process !== "undefined" && false;
|
|
6302
|
-
const [showWelcome, setShowWelcome] =
|
|
6303
|
-
|
|
6366
|
+
const [showWelcome, setShowWelcome] = useState20(isTestEnv ? false : null);
|
|
6367
|
+
useEffect22(() => {
|
|
6304
6368
|
if (isTestEnv) return;
|
|
6305
6369
|
void hasCompletedOnboarding().then((done) => setShowWelcome(!done));
|
|
6306
6370
|
}, []);
|
|
@@ -6397,7 +6461,7 @@ async function reportError(err, context = {}) {
|
|
|
6397
6461
|
const config = await resolveConfig();
|
|
6398
6462
|
if (!config.enabled || !config.endpoint) return;
|
|
6399
6463
|
const machineId = await getMachineId();
|
|
6400
|
-
const version = true ? "1.1
|
|
6464
|
+
const version = true ? "1.2.1" : "unknown";
|
|
6401
6465
|
await postReport(buildReport("error", err, context, machineId, version), config);
|
|
6402
6466
|
}
|
|
6403
6467
|
async function installCrashReporter() {
|
|
@@ -6406,7 +6470,7 @@ async function installCrashReporter() {
|
|
|
6406
6470
|
if (!config.enabled || !config.endpoint) return;
|
|
6407
6471
|
_installed = true;
|
|
6408
6472
|
const machineId = await getMachineId();
|
|
6409
|
-
const version = true ? "1.1
|
|
6473
|
+
const version = true ? "1.2.1" : "unknown";
|
|
6410
6474
|
process.on("uncaughtException", (err) => {
|
|
6411
6475
|
void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
|
|
6412
6476
|
});
|
|
@@ -6421,7 +6485,7 @@ import { jsx as jsx39 } from "react/jsx-runtime";
|
|
|
6421
6485
|
var [, , command, arg] = process.argv;
|
|
6422
6486
|
async function runCli() {
|
|
6423
6487
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
6424
|
-
process.stdout.write("1.1
|
|
6488
|
+
process.stdout.write("1.2.1\n");
|
|
6425
6489
|
return;
|
|
6426
6490
|
}
|
|
6427
6491
|
await ensureDataDirs();
|
|
@@ -6604,7 +6668,7 @@ async function ensureBrewBarRunning() {
|
|
|
6604
6668
|
await useLicenseStore.getState().initialize();
|
|
6605
6669
|
if (!useLicenseStore.getState().isPro()) return;
|
|
6606
6670
|
const { isBrewBarInstalled, installBrewBar, launchBrewBar } = await import("./brewbar-installer-GWJ76J6G.js");
|
|
6607
|
-
const { checkBrewBarVersion } = await import("./version-check-
|
|
6671
|
+
const { checkBrewBarVersion } = await import("./version-check-AIYMRDFF.js");
|
|
6608
6672
|
try {
|
|
6609
6673
|
if (!await isBrewBarInstalled()) {
|
|
6610
6674
|
console.log(t("cli_brewbarInstalling"));
|