brew-tui 1.0.0 → 1.2.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/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 useEffect23, useState as
|
|
69
|
+
import { useEffect as useEffect23, useState as useState21 } from "react";
|
|
70
70
|
import { useApp } from "ink";
|
|
71
71
|
|
|
72
72
|
// src/components/layout/app-layout.tsx
|
|
@@ -74,7 +74,32 @@ import { useRef } from "react";
|
|
|
74
74
|
import { Box as Box3 } from "ink";
|
|
75
75
|
|
|
76
76
|
// src/components/layout/header.tsx
|
|
77
|
-
import { Box, Text as Text3
|
|
77
|
+
import { Box, Text as Text3 } from "ink";
|
|
78
|
+
|
|
79
|
+
// src/hooks/use-terminal-size.ts
|
|
80
|
+
import { useEffect, useState } from "react";
|
|
81
|
+
import { useStdout } from "ink";
|
|
82
|
+
function useTerminalSize() {
|
|
83
|
+
const { stdout } = useStdout();
|
|
84
|
+
const [size, setSize] = useState(() => ({
|
|
85
|
+
columns: stdout?.columns ?? 80,
|
|
86
|
+
rows: stdout?.rows ?? 24
|
|
87
|
+
}));
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (!stdout) return;
|
|
90
|
+
const onResize = () => {
|
|
91
|
+
setSize({
|
|
92
|
+
columns: stdout.columns ?? 80,
|
|
93
|
+
rows: stdout.rows ?? 24
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
stdout.on("resize", onResize);
|
|
97
|
+
return () => {
|
|
98
|
+
stdout.off("resize", onResize);
|
|
99
|
+
};
|
|
100
|
+
}, [stdout]);
|
|
101
|
+
return size;
|
|
102
|
+
}
|
|
78
103
|
|
|
79
104
|
// src/stores/navigation-store.ts
|
|
80
105
|
import { create } from "zustand";
|
|
@@ -297,7 +322,7 @@ var GRADIENTS = {
|
|
|
297
322
|
};
|
|
298
323
|
|
|
299
324
|
// src/components/common/blinking-text.tsx
|
|
300
|
-
import { useEffect, useState } from "react";
|
|
325
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
301
326
|
import { Text as Text2 } from "ink";
|
|
302
327
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
303
328
|
function BlinkingText({
|
|
@@ -306,8 +331,8 @@ function BlinkingText({
|
|
|
306
331
|
bold = true,
|
|
307
332
|
children
|
|
308
333
|
}) {
|
|
309
|
-
const [bright, setBright] =
|
|
310
|
-
|
|
334
|
+
const [bright, setBright] = useState2(true);
|
|
335
|
+
useEffect2(() => {
|
|
311
336
|
const id = setInterval(() => setBright((b) => !b), intervalMs);
|
|
312
337
|
return () => clearInterval(id);
|
|
313
338
|
}, [intervalMs]);
|
|
@@ -324,6 +349,20 @@ var SPACING = {
|
|
|
324
349
|
xl: 6,
|
|
325
350
|
xxl: 8
|
|
326
351
|
};
|
|
352
|
+
var BREAKPOINTS = {
|
|
353
|
+
/** Below this we collapse to single-column rows (only the name fits). */
|
|
354
|
+
narrow: 50,
|
|
355
|
+
/** Below this we drop the description column but keep version. */
|
|
356
|
+
mid: 80,
|
|
357
|
+
/** At or above this we render every column comfortably. */
|
|
358
|
+
wide: 120
|
|
359
|
+
};
|
|
360
|
+
function getLayoutMode(columns) {
|
|
361
|
+
if (columns < BREAKPOINTS.narrow) return "single";
|
|
362
|
+
if (columns < BREAKPOINTS.mid) return "compact";
|
|
363
|
+
if (columns < BREAKPOINTS.wide) return "comfortable";
|
|
364
|
+
return "wide";
|
|
365
|
+
}
|
|
327
366
|
|
|
328
367
|
// src/components/layout/header.tsx
|
|
329
368
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
@@ -389,9 +428,11 @@ function Header() {
|
|
|
389
428
|
const menuMode = useNavigationStore((s) => s.menuMode);
|
|
390
429
|
const menuCursor = useNavigationStore((s) => s.menuCursor);
|
|
391
430
|
useLocaleStore((s) => s.locale);
|
|
392
|
-
const {
|
|
393
|
-
const
|
|
394
|
-
const
|
|
431
|
+
const { columns, rows } = useTerminalSize();
|
|
432
|
+
const isNarrow = columns < 95;
|
|
433
|
+
const hideLogoByWidth = columns < 45;
|
|
434
|
+
const hideLogoByHeight = rows < 32;
|
|
435
|
+
const collapseMenu = rows < 22 && !menuMode;
|
|
395
436
|
const cursorView = menuMode ? MENU_VIEWS[menuCursor] ?? null : null;
|
|
396
437
|
const logoBlock = /* @__PURE__ */ jsx3(Box, { flexDirection: "column", flexShrink: 0, children: LOGO_BREW.map((brew, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
397
438
|
/* @__PURE__ */ jsx3(GradientText, { colors: GRADIENTS.gold, children: brew }),
|
|
@@ -412,12 +453,30 @@ function Header() {
|
|
|
412
453
|
t("hint_menuOpen_suffix")
|
|
413
454
|
] }) })
|
|
414
455
|
] });
|
|
456
|
+
if (collapseMenu) {
|
|
457
|
+
const currentLabel = t(VIEW_LABEL_KEYS[currentView]);
|
|
458
|
+
const currentIsPro = isProView(currentView) || isTeamView(currentView);
|
|
459
|
+
return /* @__PURE__ */ jsxs(Box, { paddingX: SPACING.xs, children: [
|
|
460
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.success, bold: true, children: "\u25B6 " }),
|
|
461
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.success, bold: true, children: currentLabel }),
|
|
462
|
+
currentIsPro && /* @__PURE__ */ jsxs(Text3, { color: COLORS.brand, bold: true, children: [
|
|
463
|
+
" ",
|
|
464
|
+
t("pro_badge")
|
|
465
|
+
] }),
|
|
466
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.textSecondary, children: " " }),
|
|
467
|
+
/* @__PURE__ */ jsx3(BlinkingText, { color: COLORS.brand, children: "M" }),
|
|
468
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.textSecondary, children: t("hint_menuOpen_suffix") })
|
|
469
|
+
] });
|
|
470
|
+
}
|
|
415
471
|
if (isNarrow) {
|
|
416
472
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: SPACING.xs, children: [
|
|
417
|
-
logoBlock,
|
|
418
|
-
/* @__PURE__ */ jsx3(Box, { marginTop: SPACING.xs, children: menuBlock })
|
|
473
|
+
!hideLogoByWidth && !hideLogoByHeight && logoBlock,
|
|
474
|
+
/* @__PURE__ */ jsx3(Box, { marginTop: hideLogoByWidth || hideLogoByHeight ? SPACING.none : SPACING.xs, children: menuBlock })
|
|
419
475
|
] });
|
|
420
476
|
}
|
|
477
|
+
if (hideLogoByHeight) {
|
|
478
|
+
return /* @__PURE__ */ jsx3(Box, { flexDirection: "column", paddingX: SPACING.xs, children: menuBlock });
|
|
479
|
+
}
|
|
421
480
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", paddingX: SPACING.xs, alignItems: "center", children: [
|
|
422
481
|
logoBlock,
|
|
423
482
|
/* @__PURE__ */ jsx3(Box, { marginLeft: SPACING.sm, children: menuBlock })
|
|
@@ -460,8 +519,9 @@ function Footer() {
|
|
|
460
519
|
const currentView = useNavigationStore((s) => s.currentView);
|
|
461
520
|
const menuMode = useNavigationStore((s) => s.menuMode);
|
|
462
521
|
const locale = useLocaleStore((s) => s.locale);
|
|
522
|
+
const { rows } = useTerminalSize();
|
|
463
523
|
const defs = VIEW_HINT_DEFS[currentView] ?? [];
|
|
464
|
-
const showChoose = hasNumberedActions(defs) && !menuMode;
|
|
524
|
+
const showChoose = hasNumberedActions(defs) && !menuMode && rows >= 26;
|
|
465
525
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
466
526
|
showChoose && /* @__PURE__ */ jsx4(Box2, { paddingX: SPACING.xs, children: /* @__PURE__ */ jsx4(Text4, { color: COLORS.text, children: t("hint_chooseNumber") }) }),
|
|
467
527
|
/* @__PURE__ */ jsxs2(Box2, { borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, borderColor: COLORS.gold, paddingX: SPACING.xs, flexWrap: "wrap", children: [
|
|
@@ -506,31 +566,6 @@ function Footer() {
|
|
|
506
566
|
] });
|
|
507
567
|
}
|
|
508
568
|
|
|
509
|
-
// src/hooks/use-terminal-size.ts
|
|
510
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
511
|
-
import { useStdout as useStdout2 } from "ink";
|
|
512
|
-
function useTerminalSize() {
|
|
513
|
-
const { stdout } = useStdout2();
|
|
514
|
-
const [size, setSize] = useState2(() => ({
|
|
515
|
-
columns: stdout?.columns ?? 80,
|
|
516
|
-
rows: stdout?.rows ?? 24
|
|
517
|
-
}));
|
|
518
|
-
useEffect2(() => {
|
|
519
|
-
if (!stdout) return;
|
|
520
|
-
const onResize = () => {
|
|
521
|
-
setSize({
|
|
522
|
-
columns: stdout.columns ?? 80,
|
|
523
|
-
rows: stdout.rows ?? 24
|
|
524
|
-
});
|
|
525
|
-
};
|
|
526
|
-
stdout.on("resize", onResize);
|
|
527
|
-
return () => {
|
|
528
|
-
stdout.off("resize", onResize);
|
|
529
|
-
};
|
|
530
|
-
}, [stdout]);
|
|
531
|
-
return size;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
569
|
// src/hooks/use-container-size.ts
|
|
535
570
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
536
571
|
import { measureElement } from "ink";
|
|
@@ -837,12 +872,12 @@ function WelcomeView({ onContinue }) {
|
|
|
837
872
|
void markOnboardingComplete().finally(onContinue);
|
|
838
873
|
}
|
|
839
874
|
});
|
|
840
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingY: SPACING.
|
|
875
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingY: SPACING.xs, paddingX: SPACING.sm, flexShrink: 1, children: [
|
|
841
876
|
/* @__PURE__ */ jsx7(Box4, { children: /* @__PURE__ */ jsx7(GradientText, { colors: GRADIENTS.gold, bold: true, children: t("welcome_title") }) }),
|
|
842
|
-
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.
|
|
843
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.
|
|
877
|
+
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.text, wrap: "wrap", children: t("welcome_intro") }) }),
|
|
878
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
844
879
|
/* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_keysHeader") }),
|
|
845
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: SPACING.sm,
|
|
880
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: SPACING.sm, children: [
|
|
846
881
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
847
882
|
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "m" }),
|
|
848
883
|
" ",
|
|
@@ -885,11 +920,11 @@ function WelcomeView({ onContinue }) {
|
|
|
885
920
|
] })
|
|
886
921
|
] })
|
|
887
922
|
] }),
|
|
888
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.
|
|
923
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
889
924
|
/* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_proHeader") }),
|
|
890
|
-
/* @__PURE__ */ jsx7(Box4, { paddingLeft: SPACING.sm, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.textSecondary, children: t("welcome_proIntro") }) })
|
|
925
|
+
/* @__PURE__ */ jsx7(Box4, { paddingLeft: SPACING.sm, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.textSecondary, wrap: "wrap", children: t("welcome_proIntro") }) })
|
|
891
926
|
] }),
|
|
892
|
-
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.
|
|
927
|
+
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.success, bold: true, children: t("welcome_continueHint") }) })
|
|
893
928
|
] });
|
|
894
929
|
}
|
|
895
930
|
|
|
@@ -915,15 +950,16 @@ function UpgradePrompt({ viewId }) {
|
|
|
915
950
|
const pricingKey = team ? "upgrade_teamPricing" : "upgrade_pricing";
|
|
916
951
|
const buyUrlKey = team ? "upgrade_buyUrlTeam" : "upgrade_buyUrl";
|
|
917
952
|
const labelKey = team ? "upgrade_teamLabel" : "upgrade_proLabel";
|
|
918
|
-
return /* @__PURE__ */ jsx8(Box5, { flexDirection: "column", alignItems: "center", paddingY: SPACING.
|
|
953
|
+
return /* @__PURE__ */ jsx8(Box5, { flexDirection: "column", alignItems: "center", paddingY: SPACING.xs, children: /* @__PURE__ */ jsxs5(
|
|
919
954
|
Box5,
|
|
920
955
|
{
|
|
921
956
|
borderStyle: "double",
|
|
922
957
|
borderColor: COLORS.brand,
|
|
923
|
-
paddingX: SPACING.
|
|
924
|
-
paddingY: SPACING.
|
|
958
|
+
paddingX: SPACING.sm,
|
|
959
|
+
paddingY: SPACING.none,
|
|
925
960
|
flexDirection: "column",
|
|
926
961
|
alignItems: "center",
|
|
962
|
+
flexShrink: 1,
|
|
927
963
|
width: "80%",
|
|
928
964
|
children: [
|
|
929
965
|
/* @__PURE__ */ jsxs5(Text6, { bold: true, color: COLORS.brand, children: [
|
|
@@ -931,24 +967,13 @@ function UpgradePrompt({ viewId }) {
|
|
|
931
967
|
" ",
|
|
932
968
|
t(headerKey, { title })
|
|
933
969
|
] }),
|
|
934
|
-
/* @__PURE__ */ jsx8(Text6, { children: " " }),
|
|
935
970
|
/* @__PURE__ */ jsx8(Text6, { color: COLORS.text, wrap: "wrap", children: t(keys.desc) }),
|
|
936
|
-
/* @__PURE__ */
|
|
937
|
-
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", children: [
|
|
971
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", marginTop: SPACING.xs, children: [
|
|
938
972
|
/* @__PURE__ */ jsx8(Text6, { color: COLORS.info, bold: true, children: t(pricingKey) }),
|
|
939
|
-
/* @__PURE__ */ jsx8(Text6, { children: " " }),
|
|
940
973
|
/* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_buyAt") }),
|
|
941
|
-
/* @__PURE__ */
|
|
942
|
-
" ",
|
|
943
|
-
t(buyUrlKey)
|
|
944
|
-
] }),
|
|
945
|
-
/* @__PURE__ */ jsx8(Text6, { children: " " }),
|
|
974
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.sky, bold: true, children: t(buyUrlKey) }),
|
|
946
975
|
/* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_activateWith") }),
|
|
947
|
-
/* @__PURE__ */
|
|
948
|
-
" ",
|
|
949
|
-
t("upgrade_activateCmd")
|
|
950
|
-
] }),
|
|
951
|
-
/* @__PURE__ */ jsx8(Text6, { children: " " }),
|
|
976
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.success, bold: true, children: t("upgrade_activateCmd") }),
|
|
952
977
|
/* @__PURE__ */ jsx8(Text6, { color: COLORS.brand, children: t(labelKey) })
|
|
953
978
|
] })
|
|
954
979
|
]
|
|
@@ -958,7 +983,19 @@ function UpgradePrompt({ viewId }) {
|
|
|
958
983
|
|
|
959
984
|
// src/views/dashboard.tsx
|
|
960
985
|
import { useEffect as useEffect5, useMemo as useMemo2 } from "react";
|
|
961
|
-
import { Box as Box9, Text as Text12
|
|
986
|
+
import { Box as Box9, Text as Text12 } from "ink";
|
|
987
|
+
|
|
988
|
+
// src/hooks/use-visible-rows.ts
|
|
989
|
+
function useVisibleRows({
|
|
990
|
+
reservedRows,
|
|
991
|
+
fallbackReservedRows = reservedRows,
|
|
992
|
+
minRows = 3
|
|
993
|
+
}) {
|
|
994
|
+
const { height: contentHeight } = useContentSize();
|
|
995
|
+
const { rows: terminalRows } = useTerminalSize();
|
|
996
|
+
const availableRows = contentHeight > 0 ? contentHeight - reservedRows : terminalRows - fallbackReservedRows;
|
|
997
|
+
return Math.max(minRows, Math.floor(availableRows));
|
|
998
|
+
}
|
|
962
999
|
|
|
963
1000
|
// src/stores/brew-store.ts
|
|
964
1001
|
import { create as create4 } from "zustand";
|
|
@@ -1924,12 +1961,11 @@ var useComplianceStore = create8((set, get) => ({
|
|
|
1924
1961
|
}));
|
|
1925
1962
|
|
|
1926
1963
|
// src/components/common/stat-card.tsx
|
|
1927
|
-
import { Box as Box6, Text as Text7
|
|
1964
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
1928
1965
|
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1929
1966
|
function StatCard({ label, value, color = COLORS.white }) {
|
|
1930
|
-
const {
|
|
1931
|
-
const
|
|
1932
|
-
const minW = cols < 60 ? 12 : cols < 100 ? 14 : 16;
|
|
1967
|
+
const { columns } = useTerminalSize();
|
|
1968
|
+
const minW = columns < 60 ? 12 : columns < 100 ? 14 : 16;
|
|
1933
1969
|
return /* @__PURE__ */ jsxs6(
|
|
1934
1970
|
Box6,
|
|
1935
1971
|
{
|
|
@@ -1939,6 +1975,7 @@ function StatCard({ label, value, color = COLORS.white }) {
|
|
|
1939
1975
|
paddingY: SPACING.none,
|
|
1940
1976
|
flexDirection: "column",
|
|
1941
1977
|
alignItems: "center",
|
|
1978
|
+
flexShrink: 1,
|
|
1942
1979
|
minWidth: minW,
|
|
1943
1980
|
children: [
|
|
1944
1981
|
/* @__PURE__ */ jsx9(Text7, { bold: true, color, children: value }),
|
|
@@ -2048,10 +2085,6 @@ function formatDate(value) {
|
|
|
2048
2085
|
const locale = getLocale();
|
|
2049
2086
|
return date.toLocaleDateString(locale === "es" ? "es-ES" : "en-US");
|
|
2050
2087
|
}
|
|
2051
|
-
function truncate(str, maxLen) {
|
|
2052
|
-
if (str.length <= maxLen) return str;
|
|
2053
|
-
return str.slice(0, maxLen - 1) + "\u2026";
|
|
2054
|
-
}
|
|
2055
2088
|
|
|
2056
2089
|
// src/views/dashboard.tsx
|
|
2057
2090
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
@@ -2103,8 +2136,13 @@ function DashboardView() {
|
|
|
2103
2136
|
const lastFetchedAt = useBrewStore((s) => s.lastFetchedAt);
|
|
2104
2137
|
const fetchAll = useBrewStore((s) => s.fetchAll);
|
|
2105
2138
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
2106
|
-
const {
|
|
2107
|
-
const
|
|
2139
|
+
const { columns } = useTerminalSize();
|
|
2140
|
+
const splitRows = useVisibleRows({
|
|
2141
|
+
reservedRows: 18,
|
|
2142
|
+
fallbackReservedRows: 22,
|
|
2143
|
+
minRows: 2
|
|
2144
|
+
});
|
|
2145
|
+
const halfRows = Math.max(1, Math.floor(splitRows / 2));
|
|
2108
2146
|
useEffect5(() => {
|
|
2109
2147
|
fetchAll();
|
|
2110
2148
|
}, []);
|
|
@@ -2195,20 +2233,23 @@ function DashboardView() {
|
|
|
2195
2233
|
!errors.outdated && outdated.formulae.length > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2196
2234
|
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u{1F4E6}", title: t("dashboard_outdatedPackages"), gradient: GRADIENTS.fire }),
|
|
2197
2235
|
/* @__PURE__ */ jsxs11(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
2198
|
-
outdated.formulae.slice(0,
|
|
2236
|
+
outdated.formulae.slice(0, halfRows).map((pkg) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2199
2237
|
/* @__PURE__ */ jsx13(Text12, { color: COLORS.text, children: pkg.name }),
|
|
2200
2238
|
/* @__PURE__ */ jsx13(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version })
|
|
2201
2239
|
] }, pkg.name)),
|
|
2202
|
-
outdated.formulae.length >
|
|
2240
|
+
outdated.formulae.length > halfRows && /* @__PURE__ */ jsx13(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: outdated.formulae.length - halfRows }) })
|
|
2203
2241
|
] })
|
|
2204
2242
|
] }),
|
|
2205
2243
|
!errors.services && errorServices > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2206
2244
|
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("dashboard_serviceErrors"), color: COLORS.error }),
|
|
2207
|
-
/* @__PURE__ */
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2245
|
+
/* @__PURE__ */ jsxs11(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
2246
|
+
errorServiceList.slice(0, halfRows).map((s) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2247
|
+
/* @__PURE__ */ jsx13(StatusBadge, { label: t("badge_error"), variant: "error" }),
|
|
2248
|
+
/* @__PURE__ */ jsx13(Text12, { children: s.name }),
|
|
2249
|
+
s.exit_code != null && /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("common_exit", { code: s.exit_code }) })
|
|
2250
|
+
] }, s.name)),
|
|
2251
|
+
errorServiceList.length > halfRows && /* @__PURE__ */ jsx13(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: errorServiceList.length - halfRows }) })
|
|
2252
|
+
] })
|
|
2212
2253
|
] }),
|
|
2213
2254
|
isPro() && /* @__PURE__ */ jsx13(ProStatusPanel, {})
|
|
2214
2255
|
] });
|
|
@@ -2347,8 +2388,8 @@ function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
|
2347
2388
|
else if (input === "n" || input === "N") onCancel();
|
|
2348
2389
|
else if (key.escape) onCancel();
|
|
2349
2390
|
});
|
|
2350
|
-
return /* @__PURE__ */ jsxs13(Box11, { borderStyle: "double", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.xs, flexDirection: "column", children: [
|
|
2351
|
-
/* @__PURE__ */ jsx15(Text14, { bold: true, color: COLORS.text, children: message }),
|
|
2391
|
+
return /* @__PURE__ */ jsxs13(Box11, { borderStyle: "double", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.xs, flexDirection: "column", flexShrink: 1, children: [
|
|
2392
|
+
/* @__PURE__ */ jsx15(Text14, { bold: true, color: COLORS.text, wrap: "wrap", children: message }),
|
|
2352
2393
|
/* @__PURE__ */ jsxs13(Box11, { marginTop: SPACING.xs, children: [
|
|
2353
2394
|
/* @__PURE__ */ jsx15(Text14, { color: COLORS.success, children: t("confirm_yes") }),
|
|
2354
2395
|
/* @__PURE__ */ jsx15(Text14, { children: " / " }),
|
|
@@ -2405,18 +2446,6 @@ function SelectableRow({ isCurrent, children, gap = 1 }) {
|
|
|
2405
2446
|
] });
|
|
2406
2447
|
}
|
|
2407
2448
|
|
|
2408
|
-
// src/hooks/use-visible-rows.ts
|
|
2409
|
-
function useVisibleRows({
|
|
2410
|
-
reservedRows,
|
|
2411
|
-
fallbackReservedRows = reservedRows,
|
|
2412
|
-
minRows = 3
|
|
2413
|
-
}) {
|
|
2414
|
-
const { height: contentHeight } = useContentSize();
|
|
2415
|
-
const { rows: terminalRows } = useTerminalSize();
|
|
2416
|
-
const availableRows = contentHeight > 0 ? contentHeight - reservedRows : terminalRows - fallbackReservedRows;
|
|
2417
|
-
return Math.max(minRows, Math.floor(availableRows));
|
|
2418
|
-
}
|
|
2419
|
-
|
|
2420
2449
|
// src/views/installed.tsx
|
|
2421
2450
|
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2422
2451
|
function InstalledView() {
|
|
@@ -2431,8 +2460,13 @@ function InstalledView() {
|
|
|
2431
2460
|
const containerRef = useRef3(null);
|
|
2432
2461
|
const { width: containerWidth } = useContainerSize(containerRef);
|
|
2433
2462
|
const columns = containerWidth > 0 ? containerWidth : 80;
|
|
2434
|
-
const
|
|
2435
|
-
const
|
|
2463
|
+
const mode = getLayoutMode(columns);
|
|
2464
|
+
const nameWidth = mode === "single" ? Math.max(
|
|
2465
|
+
8,
|
|
2466
|
+
columns - 2
|
|
2467
|
+
/* cursor + gap */
|
|
2468
|
+
) : Math.max(12, Math.floor(columns * 0.35));
|
|
2469
|
+
const versionWidth = Math.max(8, Math.floor(columns * 0.15));
|
|
2436
2470
|
const [filter, setFilter] = useState6("");
|
|
2437
2471
|
const [cursor, setCursor] = useState6(0);
|
|
2438
2472
|
const [tab, setTab] = useState6("formulae");
|
|
@@ -2594,12 +2628,10 @@ function InstalledView() {
|
|
|
2594
2628
|
),
|
|
2595
2629
|
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 }) }),
|
|
2596
2630
|
/* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, children: [
|
|
2597
|
-
/* @__PURE__ */
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_version").padEnd(versionWidth) }),
|
|
2602
|
-
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: t("installed_col_status") })
|
|
2631
|
+
/* @__PURE__ */ jsx19(Text18, { color: COLORS.text, children: " " }),
|
|
2632
|
+
/* @__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") }) }),
|
|
2633
|
+
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") }) }),
|
|
2634
|
+
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") }) })
|
|
2603
2635
|
] }),
|
|
2604
2636
|
/* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
|
|
2605
2637
|
visible.length === 0 && /* @__PURE__ */ jsx19(Box15, { paddingY: SPACING.xs, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, italic: true, children: t("installed_noPackages") }) }),
|
|
@@ -2610,14 +2642,25 @@ function InstalledView() {
|
|
|
2610
2642
|
visible.map((item, i) => {
|
|
2611
2643
|
const idx = start + i;
|
|
2612
2644
|
const isCurrent = idx === cursor;
|
|
2645
|
+
const hasBadge = item.outdated || item.pinned || item.kegOnly || item.installedAsDependency;
|
|
2613
2646
|
return /* @__PURE__ */ jsxs16(SelectableRow, { isCurrent, children: [
|
|
2614
|
-
/* @__PURE__ */ jsx19(
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2647
|
+
/* @__PURE__ */ jsx19(Box15, { width: nameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(
|
|
2648
|
+
Text18,
|
|
2649
|
+
{
|
|
2650
|
+
bold: isCurrent,
|
|
2651
|
+
inverse: isCurrent,
|
|
2652
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
2653
|
+
wrap: "truncate-middle",
|
|
2654
|
+
children: item.name
|
|
2655
|
+
}
|
|
2656
|
+
) }),
|
|
2657
|
+
mode !== "single" && /* @__PURE__ */ jsx19(Box15, { width: versionWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.teal, wrap: "truncate", children: item.version }) }),
|
|
2658
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsx19(Box15, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: hasBadge ? /* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, children: [
|
|
2659
|
+
item.outdated && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
|
|
2660
|
+
item.pinned && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
|
|
2661
|
+
item.kegOnly && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
|
|
2662
|
+
item.installedAsDependency && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_dep"), variant: "muted" })
|
|
2663
|
+
] }) : /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, dimColor: true, wrap: "truncate", children: item.desc }) })
|
|
2621
2664
|
] }, item.name);
|
|
2622
2665
|
}),
|
|
2623
2666
|
start + MAX_VISIBLE_ROWS < allItems.length && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -2820,7 +2863,7 @@ function SearchView() {
|
|
|
2820
2863
|
const idx = start + i;
|
|
2821
2864
|
const isCurrent = idx === cursor;
|
|
2822
2865
|
return /* @__PURE__ */ jsxs17(SelectableRow, { isCurrent, children: [
|
|
2823
|
-
/* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, children: result.name }),
|
|
2866
|
+
/* @__PURE__ */ jsx20(Box16, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, wrap: "truncate-middle", children: result.name }) }),
|
|
2824
2867
|
/* @__PURE__ */ jsx20(
|
|
2825
2868
|
StatusBadge,
|
|
2826
2869
|
{
|
|
@@ -3041,7 +3084,16 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
3041
3084
|
const idx = start + i;
|
|
3042
3085
|
const isCurrent = idx === cursor;
|
|
3043
3086
|
return /* @__PURE__ */ jsxs18(SelectableRow, { isCurrent, children: [
|
|
3044
|
-
/* @__PURE__ */ jsx21(
|
|
3087
|
+
/* @__PURE__ */ jsx21(Box17, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx21(
|
|
3088
|
+
Text20,
|
|
3089
|
+
{
|
|
3090
|
+
bold: isCurrent,
|
|
3091
|
+
inverse: isCurrent,
|
|
3092
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
3093
|
+
wrap: "truncate-middle",
|
|
3094
|
+
children: pkg.name
|
|
3095
|
+
}
|
|
3096
|
+
) }),
|
|
3045
3097
|
/* @__PURE__ */ jsx21(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version }),
|
|
3046
3098
|
pkg.pinned && /* @__PURE__ */ jsx21(StatusBadge, { label: t("outdated_pinned"), variant: "info" })
|
|
3047
3099
|
] }, pkg.name);
|
|
@@ -3259,11 +3311,14 @@ function PackageInfoView() {
|
|
|
3259
3311
|
] }),
|
|
3260
3312
|
formula.dependencies.length > 0 && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3261
3313
|
/* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u{1F517}", title: t("pkgInfo_dependencies", { count: formula.dependencies.length }), gradient: GRADIENTS.ocean }),
|
|
3262
|
-
/* @__PURE__ */
|
|
3314
|
+
/* @__PURE__ */ jsxs19(Box18, { paddingLeft: SPACING.sm, flexWrap: "wrap", columnGap: 2, children: [
|
|
3315
|
+
formula.dependencies.slice(0, 30).map((dep) => /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: dep }, dep)),
|
|
3316
|
+
formula.dependencies.length > 30 && /* @__PURE__ */ jsx22(Text21, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: formula.dependencies.length - 30 }) })
|
|
3317
|
+
] })
|
|
3263
3318
|
] }),
|
|
3264
3319
|
formula.caveats && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3265
3320
|
/* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("pkgInfo_caveats"), color: COLORS.warning }),
|
|
3266
|
-
/* @__PURE__ */ jsx22(Box18, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx22(Text21, { color: COLORS.warning, children: formula.caveats }) })
|
|
3321
|
+
/* @__PURE__ */ jsx22(Box18, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx22(Text21, { color: COLORS.warning, wrap: "wrap", children: formula.caveats }) })
|
|
3267
3322
|
] })
|
|
3268
3323
|
] }),
|
|
3269
3324
|
/* @__PURE__ */ jsx22(Box18, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
|
|
@@ -3275,8 +3330,8 @@ function PackageInfoView() {
|
|
|
3275
3330
|
}
|
|
3276
3331
|
|
|
3277
3332
|
// src/views/services.tsx
|
|
3278
|
-
import { useEffect as useEffect13, useState as useState10 } from "react";
|
|
3279
|
-
import { Box as Box19, Text as Text22
|
|
3333
|
+
import { useEffect as useEffect13, useRef as useRef7, useState as useState10 } from "react";
|
|
3334
|
+
import { Box as Box19, Text as Text22 } from "ink";
|
|
3280
3335
|
import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3281
3336
|
var STATUS_VARIANTS = {
|
|
3282
3337
|
started: "success",
|
|
@@ -3296,10 +3351,16 @@ function ServicesView() {
|
|
|
3296
3351
|
const [actionInProgress, setActionInProgress] = useState10(false);
|
|
3297
3352
|
const [confirmAction, setConfirmAction] = useState10(null);
|
|
3298
3353
|
const [lastError, setLastError] = useState10(null);
|
|
3299
|
-
const
|
|
3300
|
-
const
|
|
3301
|
-
const
|
|
3302
|
-
const
|
|
3354
|
+
const containerRef = useRef7(null);
|
|
3355
|
+
const { width: containerWidth } = useContainerSize(containerRef);
|
|
3356
|
+
const cols = containerWidth > 0 ? containerWidth : 80;
|
|
3357
|
+
const mode = getLayoutMode(cols);
|
|
3358
|
+
const svcNameWidth = mode === "single" ? Math.max(
|
|
3359
|
+
8,
|
|
3360
|
+
cols - 2
|
|
3361
|
+
/* cursor + gap */
|
|
3362
|
+
) : Math.max(12, Math.floor(cols * 0.35));
|
|
3363
|
+
const svcStatusWidth = Math.max(8, Math.floor(cols * 0.15));
|
|
3303
3364
|
const MAX_VISIBLE_ROWS = useVisibleRows({
|
|
3304
3365
|
reservedRows: lastError || actionInProgress ? 8 : 6,
|
|
3305
3366
|
fallbackReservedRows: lastError || actionInProgress ? 16 : 14,
|
|
@@ -3347,7 +3408,7 @@ function ServicesView() {
|
|
|
3347
3408
|
}
|
|
3348
3409
|
const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
|
|
3349
3410
|
const visible = services.slice(start, start + MAX_VISIBLE_ROWS);
|
|
3350
|
-
return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", children: [
|
|
3411
|
+
return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", ref: containerRef, children: [
|
|
3351
3412
|
/* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_titleCount", { count: services.length }), gradient: GRADIENTS.ocean }),
|
|
3352
3413
|
confirmAction && /* @__PURE__ */ jsx23(Box19, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx23(
|
|
3353
3414
|
ConfirmDialog,
|
|
@@ -3370,12 +3431,10 @@ function ServicesView() {
|
|
|
3370
3431
|
) }),
|
|
3371
3432
|
/* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
3372
3433
|
/* @__PURE__ */ jsxs20(Box19, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, paddingBottom: SPACING.none, children: [
|
|
3373
|
-
/* @__PURE__ */
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_status").padEnd(svcStatusWidth) }),
|
|
3378
|
-
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: t("services_user") })
|
|
3434
|
+
/* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, children: " " }),
|
|
3435
|
+
/* @__PURE__ */ jsx23(Box19, { width: svcNameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(Text22, { bold: true, color: COLORS.text, wrap: "truncate", children: t("services_name") }) }),
|
|
3436
|
+
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") }) }),
|
|
3437
|
+
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") }) })
|
|
3379
3438
|
] }),
|
|
3380
3439
|
start > 0 && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3381
3440
|
" ",
|
|
@@ -3385,10 +3444,21 @@ function ServicesView() {
|
|
|
3385
3444
|
const idx = start + i;
|
|
3386
3445
|
const isCurrent = idx === cursor;
|
|
3387
3446
|
return /* @__PURE__ */ jsxs20(SelectableRow, { isCurrent, children: [
|
|
3388
|
-
/* @__PURE__ */ jsx23(
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3447
|
+
/* @__PURE__ */ jsx23(Box19, { width: svcNameWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(
|
|
3448
|
+
Text22,
|
|
3449
|
+
{
|
|
3450
|
+
bold: isCurrent,
|
|
3451
|
+
inverse: isCurrent,
|
|
3452
|
+
color: isCurrent ? COLORS.text : COLORS.muted,
|
|
3453
|
+
wrap: "truncate-middle",
|
|
3454
|
+
children: svc.name
|
|
3455
|
+
}
|
|
3456
|
+
) }),
|
|
3457
|
+
mode !== "single" && /* @__PURE__ */ jsx23(Box19, { width: svcStatusWidth, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx23(StatusBadge, { label: svc.status, variant: STATUS_VARIANTS[svc.status] }) }),
|
|
3458
|
+
mode !== "single" && mode !== "compact" && /* @__PURE__ */ jsxs20(Box19, { flexGrow: 1, flexShrink: 1, minWidth: 0, gap: SPACING.xs, children: [
|
|
3459
|
+
/* @__PURE__ */ jsx23(Text22, { color: COLORS.muted, wrap: "truncate", children: svc.user ?? "-" }),
|
|
3460
|
+
svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: t("common_exit", { code: svc.exit_code }) })
|
|
3461
|
+
] })
|
|
3392
3462
|
] }, svc.name);
|
|
3393
3463
|
}),
|
|
3394
3464
|
start + MAX_VISIBLE_ROWS < services.length && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -3407,12 +3477,18 @@ function ServicesView() {
|
|
|
3407
3477
|
}
|
|
3408
3478
|
|
|
3409
3479
|
// src/views/doctor.tsx
|
|
3410
|
-
import { useEffect as useEffect14, useRef as
|
|
3480
|
+
import { useEffect as useEffect14, useRef as useRef8, useState as useState11 } from "react";
|
|
3411
3481
|
import { Box as Box20, Text as Text23 } from "ink";
|
|
3412
3482
|
import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3413
3483
|
function DoctorView() {
|
|
3414
3484
|
const { doctorWarnings, doctorClean, loading, errors, fetchDoctor } = useBrewStore();
|
|
3415
|
-
const
|
|
3485
|
+
const [cursor, setCursor] = useState11(0);
|
|
3486
|
+
const visibleWarnings = useVisibleRows({
|
|
3487
|
+
reservedRows: 6,
|
|
3488
|
+
fallbackReservedRows: 14,
|
|
3489
|
+
minRows: 1
|
|
3490
|
+
});
|
|
3491
|
+
const mountedRef = useRef8(true);
|
|
3416
3492
|
useEffect14(() => {
|
|
3417
3493
|
mountedRef.current = true;
|
|
3418
3494
|
return () => {
|
|
@@ -3422,27 +3498,42 @@ function DoctorView() {
|
|
|
3422
3498
|
useEffect14(() => {
|
|
3423
3499
|
fetchDoctor();
|
|
3424
3500
|
}, []);
|
|
3425
|
-
useViewInput((input) => {
|
|
3426
|
-
if (input === "r" || input === "1")
|
|
3501
|
+
useViewInput((input, key) => {
|
|
3502
|
+
if (input === "r" || input === "1") {
|
|
3503
|
+
void fetchDoctor();
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3506
|
+
if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, doctorWarnings.length - 1)));
|
|
3507
|
+
else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
|
|
3427
3508
|
});
|
|
3428
3509
|
if (loading.doctor) return /* @__PURE__ */ jsx24(Loading, { message: t("loading_doctor") });
|
|
3429
3510
|
if (errors.doctor) return /* @__PURE__ */ jsx24(ErrorMessage, { message: errors.doctor });
|
|
3511
|
+
const start = Math.max(0, cursor - Math.floor(visibleWarnings / 2));
|
|
3512
|
+
const visible = doctorWarnings.slice(start, start + visibleWarnings);
|
|
3430
3513
|
return /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", children: [
|
|
3431
3514
|
/* @__PURE__ */ jsx24(SectionHeader, { emoji: "\u{1FA7A}", title: t("doctor_title"), gradient: GRADIENTS.emerald }),
|
|
3432
3515
|
/* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
3433
3516
|
doctorClean && /* @__PURE__ */ jsx24(ResultBanner, { status: "success", message: `\u2714 ${t("doctor_clean")}` }),
|
|
3434
3517
|
doctorClean === false && doctorWarnings.length === 0 && /* @__PURE__ */ jsx24(Text23, { color: COLORS.warning, children: t("doctor_warningsNotCaptured") }),
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
)
|
|
3518
|
+
start > 0 && /* @__PURE__ */ jsxs21(Text23, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3519
|
+
" ",
|
|
3520
|
+
t("scroll_moreAbove", { count: start })
|
|
3521
|
+
] }),
|
|
3522
|
+
visible.map((warning, i) => {
|
|
3523
|
+
const idx = start + i;
|
|
3524
|
+
return /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", marginBottom: SPACING.xs, borderStyle: "single", borderColor: idx === cursor ? COLORS.gold : COLORS.warning, paddingX: SPACING.xs, children: warning.split("\n").map((line, j) => /* @__PURE__ */ jsx24(Text23, { color: j === 0 ? COLORS.warning : COLORS.muted, wrap: "wrap", children: line }, `warning-${idx}-${j}-${line.slice(0, 20)}`)) }, `warning-${idx}-${warning.slice(0, 20)}`);
|
|
3525
|
+
}),
|
|
3526
|
+
start + visibleWarnings < doctorWarnings.length && /* @__PURE__ */ jsxs21(Text23, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3527
|
+
" ",
|
|
3528
|
+
t("scroll_moreBelow", { count: doctorWarnings.length - start - visibleWarnings })
|
|
3529
|
+
] })
|
|
3439
3530
|
] }),
|
|
3440
3531
|
/* @__PURE__ */ jsx24(Box20, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx24(Text23, { color: COLORS.text, bold: true, children: doctorWarnings.length > 0 ? tp("plural_warnings", doctorWarnings.length) : "" }) })
|
|
3441
3532
|
] });
|
|
3442
3533
|
}
|
|
3443
3534
|
|
|
3444
3535
|
// src/views/profiles.tsx
|
|
3445
|
-
import { useEffect as useEffect15, useRef as
|
|
3536
|
+
import { useEffect as useEffect15, useRef as useRef9, useState as useState12 } from "react";
|
|
3446
3537
|
import { Box as Box25 } from "ink";
|
|
3447
3538
|
|
|
3448
3539
|
// src/stores/profile-store.ts
|
|
@@ -3705,18 +3796,33 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
|
|
|
3705
3796
|
import { Box as Box22, Text as Text25 } from "ink";
|
|
3706
3797
|
import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3707
3798
|
function ProfileDetailMode({ profile }) {
|
|
3799
|
+
const totalRows = useVisibleRows({
|
|
3800
|
+
reservedRows: 7,
|
|
3801
|
+
fallbackReservedRows: 14,
|
|
3802
|
+
minRows: 2
|
|
3803
|
+
});
|
|
3804
|
+
const total = profile.formulae.length + profile.casks.length;
|
|
3805
|
+
const formulaeBudget = total === 0 ? 0 : Math.min(profile.formulae.length, Math.max(1, Math.round(profile.formulae.length / total * totalRows)));
|
|
3806
|
+
const casksBudget = Math.max(0, totalRows - formulaeBudget);
|
|
3807
|
+
const visibleFormulae = profile.formulae.slice(0, formulaeBudget);
|
|
3808
|
+
const visibleCasks = profile.casks.slice(0, casksBudget);
|
|
3809
|
+
const formulaeHidden = profile.formulae.length - visibleFormulae.length;
|
|
3810
|
+
const casksHidden = profile.casks.length - visibleCasks.length;
|
|
3708
3811
|
return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
|
|
3709
3812
|
/* @__PURE__ */ jsx26(Text25, { bold: true, color: COLORS.gold, children: profile.name }),
|
|
3710
|
-
/* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: profile.description }),
|
|
3813
|
+
/* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, wrap: "wrap", children: profile.description }),
|
|
3711
3814
|
/* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: t("profiles_created", { date: formatDate(profile.createdAt) }) }),
|
|
3712
3815
|
/* @__PURE__ */ jsxs23(Box22, { marginTop: SPACING.xs, flexDirection: "column", children: [
|
|
3713
3816
|
/* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_formulaeCount", { count: profile.formulae.length }) }),
|
|
3714
3817
|
/* @__PURE__ */ jsxs23(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
3715
|
-
|
|
3716
|
-
|
|
3818
|
+
visibleFormulae.map((f) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: f }, f)),
|
|
3819
|
+
formulaeHidden > 0 && /* @__PURE__ */ jsx26(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: formulaeHidden }) })
|
|
3717
3820
|
] }),
|
|
3718
3821
|
/* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_casksCount", { count: profile.casks.length }) }),
|
|
3719
|
-
/* @__PURE__ */
|
|
3822
|
+
/* @__PURE__ */ jsxs23(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
3823
|
+
visibleCasks.map((c) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: c }, c)),
|
|
3824
|
+
casksHidden > 0 && /* @__PURE__ */ jsx26(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: casksHidden }) })
|
|
3825
|
+
] })
|
|
3720
3826
|
] }),
|
|
3721
3827
|
/* @__PURE__ */ jsx26(Box22, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs23(Text25, { color: COLORS.textSecondary, children: [
|
|
3722
3828
|
"esc:",
|
|
@@ -3799,19 +3905,19 @@ function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
|
|
|
3799
3905
|
import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3800
3906
|
function ProfilesView() {
|
|
3801
3907
|
const { profileNames, selectedProfile, loading, loadError, fetchProfiles, loadProfile: loadProfile2, exportCurrent, deleteProfile: deleteProfile2, updateProfile: updateProfile2 } = useProfileStore();
|
|
3802
|
-
const [cursor, setCursor] =
|
|
3803
|
-
const [mode, setMode] =
|
|
3804
|
-
const [newName, setNewName] =
|
|
3805
|
-
const [confirmDelete, setConfirmDelete] =
|
|
3806
|
-
const [editName, setEditName] =
|
|
3807
|
-
const [editDesc, setEditDesc] =
|
|
3808
|
-
const [importLines, setImportLines] =
|
|
3809
|
-
const [importRunning, setImportRunning] =
|
|
3810
|
-
const [importHadError, setImportHadError] =
|
|
3811
|
-
const [importProfile2, setImportProfile] =
|
|
3908
|
+
const [cursor, setCursor] = useState12(0);
|
|
3909
|
+
const [mode, setMode] = useState12("list");
|
|
3910
|
+
const [newName, setNewName] = useState12("");
|
|
3911
|
+
const [confirmDelete, setConfirmDelete] = useState12(false);
|
|
3912
|
+
const [editName, setEditName] = useState12("");
|
|
3913
|
+
const [editDesc, setEditDesc] = useState12("");
|
|
3914
|
+
const [importLines, setImportLines] = useState12([]);
|
|
3915
|
+
const [importRunning, setImportRunning] = useState12(false);
|
|
3916
|
+
const [importHadError, setImportHadError] = useState12(false);
|
|
3917
|
+
const [importProfile2, setImportProfile] = useState12(null);
|
|
3812
3918
|
const { openModal, closeModal } = useModalStore();
|
|
3813
|
-
const importGenRef =
|
|
3814
|
-
const mountedRef =
|
|
3919
|
+
const importGenRef = useRef9(null);
|
|
3920
|
+
const mountedRef = useRef9(true);
|
|
3815
3921
|
useEffect15(() => {
|
|
3816
3922
|
fetchProfiles();
|
|
3817
3923
|
}, []);
|
|
@@ -3999,7 +4105,7 @@ function ProfilesView() {
|
|
|
3999
4105
|
}
|
|
4000
4106
|
|
|
4001
4107
|
// src/views/smart-cleanup.tsx
|
|
4002
|
-
import { useEffect as useEffect16, useRef as
|
|
4108
|
+
import { useEffect as useEffect16, useRef as useRef10, useState as useState13 } from "react";
|
|
4003
4109
|
import { Box as Box26, Text as Text28 } from "ink";
|
|
4004
4110
|
|
|
4005
4111
|
// src/stores/cleanup-store.ts
|
|
@@ -4123,12 +4229,17 @@ var useCleanupStore = create10((set, get) => ({
|
|
|
4123
4229
|
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4124
4230
|
function SmartCleanupView() {
|
|
4125
4231
|
const { summary, selected, loading, error, analyze, toggleSelect, selectAll } = useCleanupStore();
|
|
4126
|
-
const [cursor, setCursor] =
|
|
4127
|
-
const [confirmClean, setConfirmClean] =
|
|
4128
|
-
const [confirmForce, setConfirmForce] =
|
|
4129
|
-
const [failedNames, setFailedNames] =
|
|
4232
|
+
const [cursor, setCursor] = useState13(0);
|
|
4233
|
+
const [confirmClean, setConfirmClean] = useState13(false);
|
|
4234
|
+
const [confirmForce, setConfirmForce] = useState13(false);
|
|
4235
|
+
const [failedNames, setFailedNames] = useState13([]);
|
|
4130
4236
|
const stream = useBrewStream();
|
|
4131
|
-
const hasRefreshed =
|
|
4237
|
+
const hasRefreshed = useRef10(false);
|
|
4238
|
+
const listRows = useVisibleRows({
|
|
4239
|
+
reservedRows: confirmClean || confirmForce ? 12 : 9,
|
|
4240
|
+
fallbackReservedRows: confirmClean || confirmForce ? 18 : 14,
|
|
4241
|
+
minRows: 1
|
|
4242
|
+
});
|
|
4132
4243
|
useEffect16(() => {
|
|
4133
4244
|
analyze();
|
|
4134
4245
|
}, []);
|
|
@@ -4230,32 +4341,45 @@ function SmartCleanupView() {
|
|
|
4230
4341
|
)
|
|
4231
4342
|
] }),
|
|
4232
4343
|
candidates.length === 0 && !confirmClean && /* @__PURE__ */ jsx30(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_systemClean")}` }),
|
|
4233
|
-
candidates.length > 0 && !confirmClean &&
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4344
|
+
candidates.length > 0 && !confirmClean && (() => {
|
|
4345
|
+
const start = Math.max(0, cursor - Math.floor(listRows / 2));
|
|
4346
|
+
const visible = candidates.slice(start, start + listRows);
|
|
4347
|
+
return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
|
|
4348
|
+
start > 0 && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4349
|
+
" ",
|
|
4350
|
+
t("scroll_moreAbove", { count: start })
|
|
4351
|
+
] }),
|
|
4352
|
+
visible.map((c, i) => {
|
|
4353
|
+
const idx = start + i;
|
|
4354
|
+
const isCurrent = idx === cursor;
|
|
4355
|
+
const isSelected = selected.has(c.name);
|
|
4356
|
+
return /* @__PURE__ */ jsxs27(SelectableRow, { isCurrent, children: [
|
|
4357
|
+
/* @__PURE__ */ jsx30(Text28, { color: isSelected ? COLORS.success : COLORS.muted, children: isSelected ? "\u2611" : "\u2610" }),
|
|
4358
|
+
/* @__PURE__ */ jsx30(Text28, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: c.name }),
|
|
4359
|
+
/* @__PURE__ */ jsx30(Text28, { color: COLORS.warning, children: c.diskUsageFormatted }),
|
|
4360
|
+
/* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, children: [
|
|
4361
|
+
"[",
|
|
4362
|
+
c.reason,
|
|
4363
|
+
"]"
|
|
4364
|
+
] })
|
|
4365
|
+
] }, c.name);
|
|
4366
|
+
}),
|
|
4367
|
+
start + listRows < candidates.length && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4368
|
+
" ",
|
|
4369
|
+
t("scroll_moreBelow", { count: candidates.length - start - listRows })
|
|
4370
|
+
] }),
|
|
4371
|
+
/* @__PURE__ */ jsx30(Box26, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs27(Text28, { color: COLORS.text, bold: true, children: [
|
|
4372
|
+
cursor + 1,
|
|
4373
|
+
"/",
|
|
4374
|
+
candidates.length
|
|
4375
|
+
] }) })
|
|
4376
|
+
] });
|
|
4377
|
+
})()
|
|
4254
4378
|
] });
|
|
4255
4379
|
}
|
|
4256
4380
|
|
|
4257
4381
|
// src/views/history.tsx
|
|
4258
|
-
import { useEffect as useEffect17, useState as
|
|
4382
|
+
import { useEffect as useEffect17, useState as useState14, useMemo as useMemo5 } from "react";
|
|
4259
4383
|
import { Box as Box27, Text as Text29 } from "ink";
|
|
4260
4384
|
|
|
4261
4385
|
// src/stores/history-store.ts
|
|
@@ -4308,12 +4432,12 @@ var ACTION_LABEL_KEYS = {
|
|
|
4308
4432
|
var FILTERS = ["all", "install", "uninstall", "upgrade", "upgrade-all"];
|
|
4309
4433
|
function HistoryView() {
|
|
4310
4434
|
const { entries, loading, error, fetchHistory, clearHistory: clearHistory2 } = useHistoryStore();
|
|
4311
|
-
const [cursor, setCursor] =
|
|
4312
|
-
const [filter, setFilter] =
|
|
4313
|
-
const [searchQuery, setSearchQuery] =
|
|
4314
|
-
const [isSearching, setIsSearching] =
|
|
4315
|
-
const [confirmClear, setConfirmClear] =
|
|
4316
|
-
const [confirmReplay, setConfirmReplay] =
|
|
4435
|
+
const [cursor, setCursor] = useState14(0);
|
|
4436
|
+
const [filter, setFilter] = useState14("all");
|
|
4437
|
+
const [searchQuery, setSearchQuery] = useState14("");
|
|
4438
|
+
const [isSearching, setIsSearching] = useState14(false);
|
|
4439
|
+
const [confirmClear, setConfirmClear] = useState14(false);
|
|
4440
|
+
const [confirmReplay, setConfirmReplay] = useState14(null);
|
|
4317
4441
|
const stream = useBrewStream();
|
|
4318
4442
|
const debouncedQuery = useDebounce(searchQuery, 200);
|
|
4319
4443
|
const { openModal, closeModal } = useModalStore();
|
|
@@ -4451,8 +4575,8 @@ function HistoryView() {
|
|
|
4451
4575
|
const ts = new Date(entry.timestamp).getTime() / 1e3;
|
|
4452
4576
|
return /* @__PURE__ */ jsxs28(SelectableRow, { isCurrent, children: [
|
|
4453
4577
|
/* @__PURE__ */ jsx31(Text29, { color, bold: true, children: icon }),
|
|
4454
|
-
/* @__PURE__ */ jsx31(Text29, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: t(ACTION_LABEL_KEYS[entry.action])
|
|
4455
|
-
/* @__PURE__ */ jsx31(Text29, { color: COLORS.text, children: entry.packageName ?? t("history_all") }),
|
|
4578
|
+
/* @__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]) }) }),
|
|
4579
|
+
/* @__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") }) }),
|
|
4456
4580
|
entry.success ? /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_ok"), variant: "success" }) : /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_fail"), variant: "error" }),
|
|
4457
4581
|
/* @__PURE__ */ jsx31(Text29, { color: COLORS.muted, children: formatRelativeTime(ts) })
|
|
4458
4582
|
] }, entry.id);
|
|
@@ -4471,7 +4595,7 @@ function HistoryView() {
|
|
|
4471
4595
|
}
|
|
4472
4596
|
|
|
4473
4597
|
// src/views/security-audit.tsx
|
|
4474
|
-
import { useEffect as useEffect18, useState as
|
|
4598
|
+
import { useEffect as useEffect18, useState as useState15 } from "react";
|
|
4475
4599
|
import { Box as Box28, Text as Text30 } from "ink";
|
|
4476
4600
|
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4477
4601
|
var SEVERITY_COLORS = {
|
|
@@ -4494,9 +4618,9 @@ function isNetworkError(msg) {
|
|
|
4494
4618
|
function SecurityAuditView() {
|
|
4495
4619
|
const { summary, loading, error, scan, cachedAt } = useSecurityStore();
|
|
4496
4620
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
4497
|
-
const [cursor, setCursor] =
|
|
4498
|
-
const [expandedPkg, setExpandedPkg] =
|
|
4499
|
-
const [confirmUpgrade, setConfirmUpgrade] =
|
|
4621
|
+
const [cursor, setCursor] = useState15(0);
|
|
4622
|
+
const [expandedPkg, setExpandedPkg] = useState15(null);
|
|
4623
|
+
const [confirmUpgrade, setConfirmUpgrade] = useState15(null);
|
|
4500
4624
|
const stream = useBrewStream();
|
|
4501
4625
|
useEffect18(() => {
|
|
4502
4626
|
scan();
|
|
@@ -4603,7 +4727,7 @@ function SecurityAuditView() {
|
|
|
4603
4727
|
}
|
|
4604
4728
|
|
|
4605
4729
|
// src/views/account.tsx
|
|
4606
|
-
import { useState as
|
|
4730
|
+
import { useState as useState16 } from "react";
|
|
4607
4731
|
import { Box as Box29, Text as Text31 } from "ink";
|
|
4608
4732
|
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4609
4733
|
|
|
@@ -4685,13 +4809,13 @@ async function redeemPromoCode(code) {
|
|
|
4685
4809
|
import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4686
4810
|
function AccountView() {
|
|
4687
4811
|
const { status, license, deactivate: deactivate2, revalidate: revalidate2, degradation } = useLicenseStore();
|
|
4688
|
-
const [confirmDeactivate, setConfirmDeactivate] =
|
|
4689
|
-
const [deactivating, setDeactivating] =
|
|
4690
|
-
const [deactivateError, setDeactivateError] =
|
|
4691
|
-
const [promoMode, setPromoMode] =
|
|
4692
|
-
const [promoLoading, setPromoLoading] =
|
|
4693
|
-
const [promoResult, setPromoResult] =
|
|
4694
|
-
const [revalidating, setRevalidating] =
|
|
4812
|
+
const [confirmDeactivate, setConfirmDeactivate] = useState16(false);
|
|
4813
|
+
const [deactivating, setDeactivating] = useState16(false);
|
|
4814
|
+
const [deactivateError, setDeactivateError] = useState16(null);
|
|
4815
|
+
const [promoMode, setPromoMode] = useState16(false);
|
|
4816
|
+
const [promoLoading, setPromoLoading] = useState16(false);
|
|
4817
|
+
const [promoResult, setPromoResult] = useState16(null);
|
|
4818
|
+
const [revalidating, setRevalidating] = useState16(false);
|
|
4695
4819
|
useViewInput((input, key) => {
|
|
4696
4820
|
if (confirmDeactivate || deactivating || promoMode || revalidating) {
|
|
4697
4821
|
if (key.escape && promoMode) {
|
|
@@ -4776,16 +4900,14 @@ function AccountView() {
|
|
|
4776
4900
|
/* @__PURE__ */ jsx33(Text31, { children: formatDate(license.activatedAt) })
|
|
4777
4901
|
] })
|
|
4778
4902
|
] }),
|
|
4779
|
-
status === "free" && /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.
|
|
4903
|
+
status === "free" && /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.brand, paddingX: SPACING.sm, paddingY: SPACING.none, flexShrink: 1, children: [
|
|
4780
4904
|
/* @__PURE__ */ jsxs30(Text31, { bold: true, color: COLORS.brand, children: [
|
|
4781
4905
|
"\u2B50",
|
|
4782
4906
|
" ",
|
|
4783
4907
|
t("account_upgradeTitle")
|
|
4784
4908
|
] }),
|
|
4785
|
-
/* @__PURE__ */ jsx33(Text31, {
|
|
4786
|
-
/* @__PURE__ */ jsx33(Text31, { children: t("account_unlockDesc") }),
|
|
4909
|
+
/* @__PURE__ */ jsx33(Text31, { wrap: "wrap", children: t("account_unlockDesc") }),
|
|
4787
4910
|
/* @__PURE__ */ jsx33(Text31, { color: COLORS.info, bold: true, children: t("account_pricing") }),
|
|
4788
|
-
/* @__PURE__ */ jsx33(Text31, { children: " " }),
|
|
4789
4911
|
/* @__PURE__ */ jsxs30(Text31, { color: COLORS.muted, children: [
|
|
4790
4912
|
t("upgrade_buyAt"),
|
|
4791
4913
|
" ",
|
|
@@ -4837,13 +4959,13 @@ function AccountView() {
|
|
|
4837
4959
|
status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
|
|
4838
4960
|
revalidating ? t("account_revalidating") : "",
|
|
4839
4961
|
" ",
|
|
4840
|
-
t("app_version", { version: "1.
|
|
4962
|
+
t("app_version", { version: "1.2.0" })
|
|
4841
4963
|
] }) })
|
|
4842
4964
|
] });
|
|
4843
4965
|
}
|
|
4844
4966
|
|
|
4845
4967
|
// src/views/rollback.tsx
|
|
4846
|
-
import { useCallback as useCallback3, useEffect as useEffect19, useRef as
|
|
4968
|
+
import { useCallback as useCallback3, useEffect as useEffect19, useRef as useRef11, useState as useState17 } from "react";
|
|
4847
4969
|
import { Box as Box30, Text as Text32 } from "ink";
|
|
4848
4970
|
|
|
4849
4971
|
// src/stores/rollback-store.ts
|
|
@@ -5082,6 +5204,14 @@ function actionPrefix(action) {
|
|
|
5082
5204
|
}
|
|
5083
5205
|
function PlanView({ plan }) {
|
|
5084
5206
|
const executableCount = plan.actions.filter((a) => a.strategy !== "unavailable" && a.action !== "remove").length;
|
|
5207
|
+
const reservedForWarnings = Math.min(plan.warnings.length, 3) * 2;
|
|
5208
|
+
const actionsBudget = useVisibleRows({
|
|
5209
|
+
reservedRows: 6 + reservedForWarnings,
|
|
5210
|
+
fallbackReservedRows: 14 + reservedForWarnings,
|
|
5211
|
+
minRows: 2
|
|
5212
|
+
});
|
|
5213
|
+
const visibleActions = plan.actions.slice(0, actionsBudget);
|
|
5214
|
+
const hiddenActions = plan.actions.length - visibleActions.length;
|
|
5085
5215
|
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5086
5216
|
/* @__PURE__ */ jsxs31(Box30, { marginBottom: SPACING.xs, children: [
|
|
5087
5217
|
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.text, bold: true, children: [
|
|
@@ -5091,7 +5221,7 @@ function PlanView({ plan }) {
|
|
|
5091
5221
|
/* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, children: plan.snapshotDate })
|
|
5092
5222
|
] }),
|
|
5093
5223
|
plan.actions.length === 0 && /* @__PURE__ */ jsx34(ResultBanner, { status: "success", message: t("rollback_diff_empty") }),
|
|
5094
|
-
|
|
5224
|
+
visibleActions.map((a) => /* @__PURE__ */ jsxs31(Box30, { children: [
|
|
5095
5225
|
/* @__PURE__ */ jsxs31(Text32, { color: actionColor(a), children: [
|
|
5096
5226
|
actionPrefix(a),
|
|
5097
5227
|
" "
|
|
@@ -5114,10 +5244,18 @@ function PlanView({ plan }) {
|
|
|
5114
5244
|
"]"
|
|
5115
5245
|
] })
|
|
5116
5246
|
] }, a.packageName + a.action)),
|
|
5117
|
-
|
|
5247
|
+
hiddenActions > 0 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5248
|
+
" ",
|
|
5249
|
+
t("scroll_moreBelow", { count: hiddenActions })
|
|
5250
|
+
] }),
|
|
5251
|
+
plan.warnings.slice(0, 3).map((w) => /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.warning, wrap: "wrap", children: [
|
|
5118
5252
|
"\u26A0 ",
|
|
5119
5253
|
w
|
|
5120
5254
|
] }) }, w)),
|
|
5255
|
+
plan.warnings.length > 3 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5256
|
+
" ",
|
|
5257
|
+
t("common_andMore", { count: plan.warnings.length - 3 })
|
|
5258
|
+
] }),
|
|
5121
5259
|
/* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: plan.canExecute ? /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
5122
5260
|
"enter:",
|
|
5123
5261
|
t("rollback_confirm", { count: String(executableCount) }),
|
|
@@ -5133,13 +5271,18 @@ function PlanView({ plan }) {
|
|
|
5133
5271
|
function RollbackView() {
|
|
5134
5272
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5135
5273
|
const { snapshots, loading, error, plan, planLoading, planError, fetchSnapshots, selectSnapshot, clearPlan } = useRollbackStore();
|
|
5136
|
-
const [cursor, setCursor] =
|
|
5137
|
-
const [phase, setPhase] =
|
|
5138
|
-
const [streamLines, setStreamLines] =
|
|
5139
|
-
const [streamRunning, setStreamRunning] =
|
|
5140
|
-
const [streamError, setStreamError] =
|
|
5141
|
-
const generatorRef =
|
|
5142
|
-
const mountedRef =
|
|
5274
|
+
const [cursor, setCursor] = useState17(0);
|
|
5275
|
+
const [phase, setPhase] = useState17("list");
|
|
5276
|
+
const [streamLines, setStreamLines] = useState17([]);
|
|
5277
|
+
const [streamRunning, setStreamRunning] = useState17(false);
|
|
5278
|
+
const [streamError, setStreamError] = useState17(null);
|
|
5279
|
+
const generatorRef = useRef11(null);
|
|
5280
|
+
const mountedRef = useRef11(true);
|
|
5281
|
+
const snapshotRows = useVisibleRows({
|
|
5282
|
+
reservedRows: 6,
|
|
5283
|
+
fallbackReservedRows: 14,
|
|
5284
|
+
minRows: 1
|
|
5285
|
+
});
|
|
5143
5286
|
useEffect19(() => {
|
|
5144
5287
|
mountedRef.current = true;
|
|
5145
5288
|
return () => {
|
|
@@ -5232,22 +5375,39 @@ function RollbackView() {
|
|
|
5232
5375
|
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
|
|
5233
5376
|
/* @__PURE__ */ jsx34(SectionHeader, { emoji: "\u23EA", title: t("rollback_title"), gradient: GRADIENTS.gold }),
|
|
5234
5377
|
snapshots.length === 0 && /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(ResultBanner, { status: "info", message: t("rollback_no_snapshots") }) }),
|
|
5235
|
-
phase === "list" && snapshots.length > 0 &&
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
/* @__PURE__ */
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5378
|
+
phase === "list" && snapshots.length > 0 && (() => {
|
|
5379
|
+
const start = Math.max(0, cursor - Math.floor(snapshotRows / 2));
|
|
5380
|
+
const visible = snapshots.slice(start, start + snapshotRows);
|
|
5381
|
+
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5382
|
+
/* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, dimColor: true, children: t("rollback_select_snapshot") }),
|
|
5383
|
+
/* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5384
|
+
start > 0 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5385
|
+
" ",
|
|
5386
|
+
t("scroll_moreAbove", { count: start })
|
|
5387
|
+
] }),
|
|
5388
|
+
visible.map((s, vi) => {
|
|
5389
|
+
const i = start + vi;
|
|
5390
|
+
return /* @__PURE__ */ jsxs31(SelectableRow, { isCurrent: i === cursor, children: [
|
|
5391
|
+
/* @__PURE__ */ jsx34(Text32, { bold: i === cursor, color: i === cursor ? COLORS.text : COLORS.muted, children: s.label ?? t("rollback_snapshot_auto") }),
|
|
5392
|
+
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
5393
|
+
" \u2014 ",
|
|
5394
|
+
new Date(s.capturedAt).toLocaleString()
|
|
5395
|
+
] }),
|
|
5396
|
+
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.muted, dimColor: true, children: [
|
|
5397
|
+
" ",
|
|
5398
|
+
"(",
|
|
5399
|
+
tp("packages", s.formulae.length + s.casks.length),
|
|
5400
|
+
")"
|
|
5401
|
+
] })
|
|
5402
|
+
] }, s.capturedAt);
|
|
5403
|
+
}),
|
|
5404
|
+
start + snapshotRows < snapshots.length && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5405
|
+
" ",
|
|
5406
|
+
t("scroll_moreBelow", { count: snapshots.length - start - snapshotRows })
|
|
5407
|
+
] })
|
|
5248
5408
|
] })
|
|
5249
|
-
] }
|
|
5250
|
-
|
|
5409
|
+
] });
|
|
5410
|
+
})(),
|
|
5251
5411
|
phase === "plan" && /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
|
|
5252
5412
|
planLoading && /* @__PURE__ */ jsx34(Loading, { message: t("rollback_capturing") }),
|
|
5253
5413
|
planError && /* @__PURE__ */ jsx34(ErrorMessage, { message: planError }),
|
|
@@ -5267,7 +5427,7 @@ function RollbackView() {
|
|
|
5267
5427
|
}
|
|
5268
5428
|
|
|
5269
5429
|
// src/views/brewfile.tsx
|
|
5270
|
-
import { useCallback as useCallback4, useEffect as useEffect20, useRef as
|
|
5430
|
+
import { useCallback as useCallback4, useEffect as useEffect20, useRef as useRef12, useState as useState18 } from "react";
|
|
5271
5431
|
import { Box as Box31, Text as Text33 } from "ink";
|
|
5272
5432
|
import { TextInput as TextInput6 } from "@inkjs/ui";
|
|
5273
5433
|
import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
@@ -5313,13 +5473,13 @@ function DriftSummary({ drift }) {
|
|
|
5313
5473
|
function BrewfileView() {
|
|
5314
5474
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5315
5475
|
const { schema, drift, loading, driftLoading, error, load, createFromCurrent } = useBrewfileStore();
|
|
5316
|
-
const [phase, setPhase] =
|
|
5317
|
-
const [streamLines, setStreamLines] =
|
|
5318
|
-
const [streamRunning, setStreamRunning] =
|
|
5319
|
-
const [streamError, setStreamError] =
|
|
5320
|
-
const [resultMessage, setResultMessage] =
|
|
5321
|
-
const generatorRef =
|
|
5322
|
-
const mountedRef =
|
|
5476
|
+
const [phase, setPhase] = useState18("overview");
|
|
5477
|
+
const [streamLines, setStreamLines] = useState18([]);
|
|
5478
|
+
const [streamRunning, setStreamRunning] = useState18(false);
|
|
5479
|
+
const [streamError, setStreamError] = useState18(null);
|
|
5480
|
+
const [resultMessage, setResultMessage] = useState18("");
|
|
5481
|
+
const generatorRef = useRef12(null);
|
|
5482
|
+
const mountedRef = useRef12(true);
|
|
5323
5483
|
useEffect20(() => {
|
|
5324
5484
|
mountedRef.current = true;
|
|
5325
5485
|
void load();
|
|
@@ -5496,7 +5656,7 @@ function BrewfileView() {
|
|
|
5496
5656
|
}
|
|
5497
5657
|
|
|
5498
5658
|
// src/views/sync.tsx
|
|
5499
|
-
import { useCallback as useCallback5, useEffect as useEffect21, useState as
|
|
5659
|
+
import { useCallback as useCallback5, useEffect as useEffect21, useState as useState19 } from "react";
|
|
5500
5660
|
import { Box as Box32, Text as Text34 } from "ink";
|
|
5501
5661
|
import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5502
5662
|
function OverviewSection({
|
|
@@ -5547,8 +5707,22 @@ function ConflictsList({
|
|
|
5547
5707
|
entries,
|
|
5548
5708
|
cursor
|
|
5549
5709
|
}) {
|
|
5710
|
+
const availableRows = useVisibleRows({
|
|
5711
|
+
reservedRows: 8,
|
|
5712
|
+
fallbackReservedRows: 14,
|
|
5713
|
+
minRows: 4
|
|
5714
|
+
});
|
|
5715
|
+
const perEntryRows = 4;
|
|
5716
|
+
const maxEntries = Math.max(1, Math.floor(availableRows / perEntryRows));
|
|
5717
|
+
const start = Math.max(0, cursor - Math.floor(maxEntries / 2));
|
|
5718
|
+
const visible = entries.slice(start, start + maxEntries);
|
|
5550
5719
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5551
|
-
|
|
5720
|
+
start > 0 && /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5721
|
+
" ",
|
|
5722
|
+
t("scroll_moreAbove", { count: start })
|
|
5723
|
+
] }),
|
|
5724
|
+
visible.map((entry, vi) => {
|
|
5725
|
+
const i = start + vi;
|
|
5552
5726
|
const { conflict, resolution } = entry;
|
|
5553
5727
|
const isActive = i === cursor;
|
|
5554
5728
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginBottom: SPACING.xs, children: [
|
|
@@ -5586,6 +5760,10 @@ function ConflictsList({
|
|
|
5586
5760
|
] })
|
|
5587
5761
|
] }, `${conflict.packageName}-${conflict.remoteMachine}`);
|
|
5588
5762
|
}),
|
|
5763
|
+
start + maxEntries < entries.length && /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5764
|
+
" ",
|
|
5765
|
+
t("scroll_moreBelow", { count: entries.length - start - maxEntries })
|
|
5766
|
+
] }),
|
|
5589
5767
|
/* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
|
|
5590
5768
|
"j/k:",
|
|
5591
5769
|
t("hint_navigate"),
|
|
@@ -5604,10 +5782,10 @@ function SyncView() {
|
|
|
5604
5782
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5605
5783
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
5606
5784
|
const { config, lastResult, conflicts, loading, error, initialize, syncNow, resolveConflicts } = useSyncStore();
|
|
5607
|
-
const [phase, setPhase] =
|
|
5608
|
-
const [syncError, setSyncError] =
|
|
5609
|
-
const [conflictEntries, setConflictEntries] =
|
|
5610
|
-
const [cursor, setCursor] =
|
|
5785
|
+
const [phase, setPhase] = useState19("overview");
|
|
5786
|
+
const [syncError, setSyncError] = useState19(null);
|
|
5787
|
+
const [conflictEntries, setConflictEntries] = useState19([]);
|
|
5788
|
+
const [cursor, setCursor] = useState19(0);
|
|
5611
5789
|
useEffect21(() => {
|
|
5612
5790
|
void initialize(isPro());
|
|
5613
5791
|
}, []);
|
|
@@ -5776,7 +5954,7 @@ function SyncView() {
|
|
|
5776
5954
|
}
|
|
5777
5955
|
|
|
5778
5956
|
// src/views/compliance.tsx
|
|
5779
|
-
import { useCallback as useCallback6, useEffect as useEffect22, useRef as
|
|
5957
|
+
import { useCallback as useCallback6, useEffect as useEffect22, useRef as useRef13, useState as useState20 } from "react";
|
|
5780
5958
|
import { Box as Box33, Text as Text35 } from "ink";
|
|
5781
5959
|
import { TextInput as TextInput7 } from "@inkjs/ui";
|
|
5782
5960
|
|
|
@@ -5857,38 +6035,58 @@ function ViolationItem({ violation }) {
|
|
|
5857
6035
|
prefix,
|
|
5858
6036
|
" "
|
|
5859
6037
|
] }),
|
|
5860
|
-
/* @__PURE__ */ jsx37(Text35, { color, children: violation.detail })
|
|
6038
|
+
/* @__PURE__ */ jsx37(Text35, { color, wrap: "wrap", children: violation.detail })
|
|
5861
6039
|
] });
|
|
5862
6040
|
}
|
|
5863
6041
|
function ViolationList({ violations }) {
|
|
5864
6042
|
const errors = violations.filter((v) => v.severity === "error");
|
|
5865
6043
|
const warnings = violations.filter((v) => v.severity === "warning");
|
|
6044
|
+
const totalRows = useVisibleRows({
|
|
6045
|
+
reservedRows: 11,
|
|
6046
|
+
fallbackReservedRows: 18,
|
|
6047
|
+
minRows: 2
|
|
6048
|
+
});
|
|
6049
|
+
const total = errors.length + warnings.length;
|
|
6050
|
+
const errorBudget = total === 0 ? 0 : Math.min(errors.length, Math.max(1, Math.round(errors.length / total * totalRows)));
|
|
6051
|
+
const warningBudget = Math.max(0, totalRows - errorBudget);
|
|
6052
|
+
const visibleErrors = errors.slice(0, errorBudget);
|
|
6053
|
+
const visibleWarnings = warnings.slice(0, warningBudget);
|
|
6054
|
+
const errorsHidden = errors.length - visibleErrors.length;
|
|
6055
|
+
const warningsHidden = warnings.length - visibleWarnings.length;
|
|
5866
6056
|
return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5867
6057
|
errors.length > 0 && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginBottom: SPACING.xs, children: [
|
|
5868
6058
|
/* @__PURE__ */ jsxs34(Text35, { color: COLORS.error, bold: true, children: [
|
|
5869
6059
|
t("compliance_violations", { count: String(errors.length) }),
|
|
5870
6060
|
" (errors)"
|
|
5871
6061
|
] }),
|
|
5872
|
-
|
|
6062
|
+
visibleErrors.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`)),
|
|
6063
|
+
errorsHidden > 0 && /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
6064
|
+
" ",
|
|
6065
|
+
t("scroll_moreBelow", { count: errorsHidden })
|
|
6066
|
+
] })
|
|
5873
6067
|
] }),
|
|
5874
6068
|
warnings.length > 0 && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
|
|
5875
6069
|
/* @__PURE__ */ jsxs34(Text35, { color: COLORS.warning, bold: true, children: [
|
|
5876
6070
|
t("compliance_violations", { count: String(warnings.length) }),
|
|
5877
6071
|
" (warnings)"
|
|
5878
6072
|
] }),
|
|
5879
|
-
|
|
6073
|
+
visibleWarnings.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`)),
|
|
6074
|
+
warningsHidden > 0 && /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
6075
|
+
" ",
|
|
6076
|
+
t("scroll_moreBelow", { count: warningsHidden })
|
|
6077
|
+
] })
|
|
5880
6078
|
] })
|
|
5881
6079
|
] });
|
|
5882
6080
|
}
|
|
5883
6081
|
function ComplianceView() {
|
|
5884
6082
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5885
6083
|
const { policy, report, loading, error, importPolicy, runCheck } = useComplianceStore();
|
|
5886
|
-
const [phase, setPhase] =
|
|
5887
|
-
const [resultMessage, setResultMessage] =
|
|
5888
|
-
const [streamLines, setStreamLines] =
|
|
5889
|
-
const [streamRunning, setStreamRunning] =
|
|
5890
|
-
const generatorRef =
|
|
5891
|
-
const mountedRef =
|
|
6084
|
+
const [phase, setPhase] = useState20("overview");
|
|
6085
|
+
const [resultMessage, setResultMessage] = useState20(null);
|
|
6086
|
+
const [streamLines, setStreamLines] = useState20([]);
|
|
6087
|
+
const [streamRunning, setStreamRunning] = useState20(false);
|
|
6088
|
+
const generatorRef = useRef13(null);
|
|
6089
|
+
const mountedRef = useRef13(true);
|
|
5892
6090
|
useEffect22(() => {
|
|
5893
6091
|
mountedRef.current = true;
|
|
5894
6092
|
return () => {
|
|
@@ -6147,7 +6345,7 @@ function App() {
|
|
|
6147
6345
|
const { exit } = useApp();
|
|
6148
6346
|
const currentView = useNavigationStore((s) => s.currentView);
|
|
6149
6347
|
const isTestEnv = typeof process !== "undefined" && false;
|
|
6150
|
-
const [showWelcome, setShowWelcome] =
|
|
6348
|
+
const [showWelcome, setShowWelcome] = useState21(isTestEnv ? false : null);
|
|
6151
6349
|
useEffect23(() => {
|
|
6152
6350
|
if (isTestEnv) return;
|
|
6153
6351
|
void hasCompletedOnboarding().then((done) => setShowWelcome(!done));
|
|
@@ -6245,7 +6443,7 @@ async function reportError(err, context = {}) {
|
|
|
6245
6443
|
const config = await resolveConfig();
|
|
6246
6444
|
if (!config.enabled || !config.endpoint) return;
|
|
6247
6445
|
const machineId = await getMachineId();
|
|
6248
|
-
const version = true ? "1.
|
|
6446
|
+
const version = true ? "1.2.0" : "unknown";
|
|
6249
6447
|
await postReport(buildReport("error", err, context, machineId, version), config);
|
|
6250
6448
|
}
|
|
6251
6449
|
async function installCrashReporter() {
|
|
@@ -6254,7 +6452,7 @@ async function installCrashReporter() {
|
|
|
6254
6452
|
if (!config.enabled || !config.endpoint) return;
|
|
6255
6453
|
_installed = true;
|
|
6256
6454
|
const machineId = await getMachineId();
|
|
6257
|
-
const version = true ? "1.
|
|
6455
|
+
const version = true ? "1.2.0" : "unknown";
|
|
6258
6456
|
process.on("uncaughtException", (err) => {
|
|
6259
6457
|
void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
|
|
6260
6458
|
});
|
|
@@ -6269,7 +6467,7 @@ import { jsx as jsx39 } from "react/jsx-runtime";
|
|
|
6269
6467
|
var [, , command, arg] = process.argv;
|
|
6270
6468
|
async function runCli() {
|
|
6271
6469
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
6272
|
-
process.stdout.write("1.
|
|
6470
|
+
process.stdout.write("1.2.0\n");
|
|
6273
6471
|
return;
|
|
6274
6472
|
}
|
|
6275
6473
|
await ensureDataDirs();
|
|
@@ -6452,7 +6650,7 @@ async function ensureBrewBarRunning() {
|
|
|
6452
6650
|
await useLicenseStore.getState().initialize();
|
|
6453
6651
|
if (!useLicenseStore.getState().isPro()) return;
|
|
6454
6652
|
const { isBrewBarInstalled, installBrewBar, launchBrewBar } = await import("./brewbar-installer-GWJ76J6G.js");
|
|
6455
|
-
const { checkBrewBarVersion } = await import("./version-check-
|
|
6653
|
+
const { checkBrewBarVersion } = await import("./version-check-MJZDQG73.js");
|
|
6456
6654
|
try {
|
|
6457
6655
|
if (!await isBrewBarInstalled()) {
|
|
6458
6656
|
console.log(t("cli_brewbarInstalling"));
|