brew-tui 0.9.2 → 1.1.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,14 +66,40 @@ 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
|
|
73
|
+
import { useRef } from "react";
|
|
73
74
|
import { Box as Box3 } from "ink";
|
|
74
75
|
|
|
75
76
|
// src/components/layout/header.tsx
|
|
76
|
-
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
|
+
}
|
|
77
103
|
|
|
78
104
|
// src/stores/navigation-store.ts
|
|
79
105
|
import { create } from "zustand";
|
|
@@ -296,7 +322,7 @@ var GRADIENTS = {
|
|
|
296
322
|
};
|
|
297
323
|
|
|
298
324
|
// src/components/common/blinking-text.tsx
|
|
299
|
-
import { useEffect, useState } from "react";
|
|
325
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
300
326
|
import { Text as Text2 } from "ink";
|
|
301
327
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
302
328
|
function BlinkingText({
|
|
@@ -305,8 +331,8 @@ function BlinkingText({
|
|
|
305
331
|
bold = true,
|
|
306
332
|
children
|
|
307
333
|
}) {
|
|
308
|
-
const [bright, setBright] =
|
|
309
|
-
|
|
334
|
+
const [bright, setBright] = useState2(true);
|
|
335
|
+
useEffect2(() => {
|
|
310
336
|
const id = setInterval(() => setBright((b) => !b), intervalMs);
|
|
311
337
|
return () => clearInterval(id);
|
|
312
338
|
}, [intervalMs]);
|
|
@@ -388,9 +414,11 @@ function Header() {
|
|
|
388
414
|
const menuMode = useNavigationStore((s) => s.menuMode);
|
|
389
415
|
const menuCursor = useNavigationStore((s) => s.menuCursor);
|
|
390
416
|
useLocaleStore((s) => s.locale);
|
|
391
|
-
const {
|
|
392
|
-
const
|
|
393
|
-
const
|
|
417
|
+
const { columns, rows } = useTerminalSize();
|
|
418
|
+
const isNarrow = columns < 95;
|
|
419
|
+
const hideLogoByWidth = columns < 45;
|
|
420
|
+
const hideLogoByHeight = rows < 32;
|
|
421
|
+
const collapseMenu = rows < 22 && !menuMode;
|
|
394
422
|
const cursorView = menuMode ? MENU_VIEWS[menuCursor] ?? null : null;
|
|
395
423
|
const logoBlock = /* @__PURE__ */ jsx3(Box, { flexDirection: "column", flexShrink: 0, children: LOGO_BREW.map((brew, i) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
396
424
|
/* @__PURE__ */ jsx3(GradientText, { colors: GRADIENTS.gold, children: brew }),
|
|
@@ -411,12 +439,30 @@ function Header() {
|
|
|
411
439
|
t("hint_menuOpen_suffix")
|
|
412
440
|
] }) })
|
|
413
441
|
] });
|
|
442
|
+
if (collapseMenu) {
|
|
443
|
+
const currentLabel = t(VIEW_LABEL_KEYS[currentView]);
|
|
444
|
+
const currentIsPro = isProView(currentView) || isTeamView(currentView);
|
|
445
|
+
return /* @__PURE__ */ jsxs(Box, { paddingX: SPACING.xs, children: [
|
|
446
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.success, bold: true, children: "\u25B6 " }),
|
|
447
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.success, bold: true, children: currentLabel }),
|
|
448
|
+
currentIsPro && /* @__PURE__ */ jsxs(Text3, { color: COLORS.brand, bold: true, children: [
|
|
449
|
+
" ",
|
|
450
|
+
t("pro_badge")
|
|
451
|
+
] }),
|
|
452
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.textSecondary, children: " " }),
|
|
453
|
+
/* @__PURE__ */ jsx3(BlinkingText, { color: COLORS.brand, children: "M" }),
|
|
454
|
+
/* @__PURE__ */ jsx3(Text3, { color: COLORS.textSecondary, children: t("hint_menuOpen_suffix") })
|
|
455
|
+
] });
|
|
456
|
+
}
|
|
414
457
|
if (isNarrow) {
|
|
415
458
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: SPACING.xs, children: [
|
|
416
|
-
logoBlock,
|
|
417
|
-
/* @__PURE__ */ jsx3(Box, { marginTop: SPACING.xs, children: menuBlock })
|
|
459
|
+
!hideLogoByWidth && !hideLogoByHeight && logoBlock,
|
|
460
|
+
/* @__PURE__ */ jsx3(Box, { marginTop: hideLogoByWidth || hideLogoByHeight ? SPACING.none : SPACING.xs, children: menuBlock })
|
|
418
461
|
] });
|
|
419
462
|
}
|
|
463
|
+
if (hideLogoByHeight) {
|
|
464
|
+
return /* @__PURE__ */ jsx3(Box, { flexDirection: "column", paddingX: SPACING.xs, children: menuBlock });
|
|
465
|
+
}
|
|
420
466
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", paddingX: SPACING.xs, alignItems: "center", children: [
|
|
421
467
|
logoBlock,
|
|
422
468
|
/* @__PURE__ */ jsx3(Box, { marginLeft: SPACING.sm, children: menuBlock })
|
|
@@ -459,8 +505,9 @@ function Footer() {
|
|
|
459
505
|
const currentView = useNavigationStore((s) => s.currentView);
|
|
460
506
|
const menuMode = useNavigationStore((s) => s.menuMode);
|
|
461
507
|
const locale = useLocaleStore((s) => s.locale);
|
|
508
|
+
const { rows } = useTerminalSize();
|
|
462
509
|
const defs = VIEW_HINT_DEFS[currentView] ?? [];
|
|
463
|
-
const showChoose = hasNumberedActions(defs) && !menuMode;
|
|
510
|
+
const showChoose = hasNumberedActions(defs) && !menuMode && rows >= 26;
|
|
464
511
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
465
512
|
showChoose && /* @__PURE__ */ jsx4(Box2, { paddingX: SPACING.xs, children: /* @__PURE__ */ jsx4(Text4, { color: COLORS.text, children: t("hint_chooseNumber") }) }),
|
|
466
513
|
/* @__PURE__ */ jsxs2(Box2, { borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, borderColor: COLORS.gold, paddingX: SPACING.xs, flexWrap: "wrap", children: [
|
|
@@ -505,13 +552,64 @@ function Footer() {
|
|
|
505
552
|
] });
|
|
506
553
|
}
|
|
507
554
|
|
|
555
|
+
// src/hooks/use-container-size.ts
|
|
556
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
557
|
+
import { measureElement } from "ink";
|
|
558
|
+
function useContainerSize(ref) {
|
|
559
|
+
const terminal = useTerminalSize();
|
|
560
|
+
const [size, setSize] = useState3({ width: 0, height: 0 });
|
|
561
|
+
useEffect3(() => {
|
|
562
|
+
if (!ref.current) return;
|
|
563
|
+
const measured = measureElement(ref.current);
|
|
564
|
+
setSize(
|
|
565
|
+
(prev) => prev.width === measured.width && prev.height === measured.height ? prev : measured
|
|
566
|
+
);
|
|
567
|
+
}, [ref, terminal.columns, terminal.rows]);
|
|
568
|
+
return size;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// src/components/layout/content-size-context.tsx
|
|
572
|
+
import { createContext, useContext } from "react";
|
|
573
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
574
|
+
var EMPTY_CONTENT_SIZE = { width: 0, height: 0 };
|
|
575
|
+
var ContentSizeContext = createContext(EMPTY_CONTENT_SIZE);
|
|
576
|
+
function ContentSizeProvider({
|
|
577
|
+
children,
|
|
578
|
+
value
|
|
579
|
+
}) {
|
|
580
|
+
return /* @__PURE__ */ jsx5(ContentSizeContext.Provider, { value, children });
|
|
581
|
+
}
|
|
582
|
+
function useContentSize() {
|
|
583
|
+
return useContext(ContentSizeContext);
|
|
584
|
+
}
|
|
585
|
+
|
|
508
586
|
// src/components/layout/app-layout.tsx
|
|
509
|
-
import { jsx as
|
|
587
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
510
588
|
function AppLayout({ children }) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
589
|
+
const { rows } = useTerminalSize();
|
|
590
|
+
const contentRef = useRef(null);
|
|
591
|
+
const contentSize = useContainerSize(contentRef);
|
|
592
|
+
const innerContentSize = {
|
|
593
|
+
width: Math.max(0, contentSize.width - SPACING.sm * 2),
|
|
594
|
+
height: Math.max(0, contentSize.height - SPACING.xs * 2)
|
|
595
|
+
};
|
|
596
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", height: rows, overflow: "hidden", children: [
|
|
597
|
+
/* @__PURE__ */ jsx6(Box3, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Header, {}) }),
|
|
598
|
+
/* @__PURE__ */ jsx6(
|
|
599
|
+
Box3,
|
|
600
|
+
{
|
|
601
|
+
ref: contentRef,
|
|
602
|
+
flexDirection: "column",
|
|
603
|
+
flexGrow: 1,
|
|
604
|
+
flexShrink: 1,
|
|
605
|
+
minHeight: 0,
|
|
606
|
+
overflow: "hidden",
|
|
607
|
+
paddingX: SPACING.sm,
|
|
608
|
+
paddingY: SPACING.xs,
|
|
609
|
+
children: /* @__PURE__ */ jsx6(ContentSizeProvider, { value: innerContentSize, children })
|
|
610
|
+
}
|
|
611
|
+
),
|
|
612
|
+
/* @__PURE__ */ jsx6(Box3, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Footer, {}) })
|
|
515
613
|
] });
|
|
516
614
|
}
|
|
517
615
|
|
|
@@ -737,7 +835,7 @@ async function markOnboardingComplete() {
|
|
|
737
835
|
}
|
|
738
836
|
|
|
739
837
|
// src/views/welcome.tsx
|
|
740
|
-
import { useEffect as
|
|
838
|
+
import { useEffect as useEffect4 } from "react";
|
|
741
839
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
742
840
|
|
|
743
841
|
// src/hooks/use-view-input.ts
|
|
@@ -749,9 +847,9 @@ function useViewInput(handler, opts) {
|
|
|
749
847
|
}
|
|
750
848
|
|
|
751
849
|
// src/views/welcome.tsx
|
|
752
|
-
import { jsx as
|
|
850
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
753
851
|
function WelcomeView({ onContinue }) {
|
|
754
|
-
|
|
852
|
+
useEffect4(() => {
|
|
755
853
|
return () => {
|
|
756
854
|
};
|
|
757
855
|
}, []);
|
|
@@ -760,65 +858,65 @@ function WelcomeView({ onContinue }) {
|
|
|
760
858
|
void markOnboardingComplete().finally(onContinue);
|
|
761
859
|
}
|
|
762
860
|
});
|
|
763
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingY: SPACING.
|
|
764
|
-
/* @__PURE__ */
|
|
765
|
-
/* @__PURE__ */
|
|
766
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.
|
|
767
|
-
/* @__PURE__ */
|
|
768
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: SPACING.sm,
|
|
861
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingY: SPACING.xs, paddingX: SPACING.sm, flexShrink: 1, children: [
|
|
862
|
+
/* @__PURE__ */ jsx7(Box4, { children: /* @__PURE__ */ jsx7(GradientText, { colors: GRADIENTS.gold, bold: true, children: t("welcome_title") }) }),
|
|
863
|
+
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.text, wrap: "wrap", children: t("welcome_intro") }) }),
|
|
864
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
865
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_keysHeader") }),
|
|
866
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: SPACING.sm, children: [
|
|
769
867
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
770
|
-
/* @__PURE__ */
|
|
868
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "m" }),
|
|
771
869
|
" ",
|
|
772
870
|
t("welcome_keyMenu")
|
|
773
871
|
] }),
|
|
774
872
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
775
|
-
/* @__PURE__ */
|
|
873
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "\u2191 \u2193" }),
|
|
776
874
|
" ",
|
|
777
875
|
t("welcome_keyMove")
|
|
778
876
|
] }),
|
|
779
877
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
780
|
-
/* @__PURE__ */
|
|
878
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "1-9" }),
|
|
781
879
|
" ",
|
|
782
880
|
t("welcome_keyAction")
|
|
783
881
|
] }),
|
|
784
882
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
785
|
-
/* @__PURE__ */
|
|
883
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "Enter" }),
|
|
786
884
|
" ",
|
|
787
885
|
t("welcome_keySelect")
|
|
788
886
|
] }),
|
|
789
887
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
790
|
-
/* @__PURE__ */
|
|
888
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "S" }),
|
|
791
889
|
" ",
|
|
792
890
|
t("welcome_keySearch")
|
|
793
891
|
] }),
|
|
794
892
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
795
|
-
/* @__PURE__ */
|
|
893
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "Esc" }),
|
|
796
894
|
" ",
|
|
797
895
|
t("welcome_keyBack")
|
|
798
896
|
] }),
|
|
799
897
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
800
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "L" }),
|
|
801
899
|
" ",
|
|
802
900
|
t("welcome_keyLocale")
|
|
803
901
|
] }),
|
|
804
902
|
/* @__PURE__ */ jsxs4(Text5, { children: [
|
|
805
|
-
/* @__PURE__ */
|
|
903
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.gold, bold: true, children: "q" }),
|
|
806
904
|
" ",
|
|
807
905
|
t("welcome_keyQuit")
|
|
808
906
|
] })
|
|
809
907
|
] })
|
|
810
908
|
] }),
|
|
811
|
-
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.
|
|
812
|
-
/* @__PURE__ */
|
|
813
|
-
/* @__PURE__ */
|
|
909
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
910
|
+
/* @__PURE__ */ jsx7(Text5, { color: COLORS.muted, children: t("welcome_proHeader") }),
|
|
911
|
+
/* @__PURE__ */ jsx7(Box4, { paddingLeft: SPACING.sm, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.textSecondary, wrap: "wrap", children: t("welcome_proIntro") }) })
|
|
814
912
|
] }),
|
|
815
|
-
/* @__PURE__ */
|
|
913
|
+
/* @__PURE__ */ jsx7(Box4, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx7(Text5, { color: COLORS.success, bold: true, children: t("welcome_continueHint") }) })
|
|
816
914
|
] });
|
|
817
915
|
}
|
|
818
916
|
|
|
819
917
|
// src/components/common/upgrade-prompt.tsx
|
|
820
918
|
import { Box as Box5, Text as Text6 } from "ink";
|
|
821
|
-
import { jsx as
|
|
919
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
822
920
|
var FEATURE_KEYS = {
|
|
823
921
|
profiles: { title: "upgrade_profiles", desc: "upgrade_profilesDesc" },
|
|
824
922
|
"smart-cleanup": { title: "upgrade_cleanup", desc: "upgrade_cleanupDesc" },
|
|
@@ -838,15 +936,16 @@ function UpgradePrompt({ viewId }) {
|
|
|
838
936
|
const pricingKey = team ? "upgrade_teamPricing" : "upgrade_pricing";
|
|
839
937
|
const buyUrlKey = team ? "upgrade_buyUrlTeam" : "upgrade_buyUrl";
|
|
840
938
|
const labelKey = team ? "upgrade_teamLabel" : "upgrade_proLabel";
|
|
841
|
-
return /* @__PURE__ */
|
|
939
|
+
return /* @__PURE__ */ jsx8(Box5, { flexDirection: "column", alignItems: "center", paddingY: SPACING.xs, children: /* @__PURE__ */ jsxs5(
|
|
842
940
|
Box5,
|
|
843
941
|
{
|
|
844
942
|
borderStyle: "double",
|
|
845
943
|
borderColor: COLORS.brand,
|
|
846
|
-
paddingX: SPACING.
|
|
847
|
-
paddingY: SPACING.
|
|
944
|
+
paddingX: SPACING.sm,
|
|
945
|
+
paddingY: SPACING.none,
|
|
848
946
|
flexDirection: "column",
|
|
849
947
|
alignItems: "center",
|
|
948
|
+
flexShrink: 1,
|
|
850
949
|
width: "80%",
|
|
851
950
|
children: [
|
|
852
951
|
/* @__PURE__ */ jsxs5(Text6, { bold: true, color: COLORS.brand, children: [
|
|
@@ -854,25 +953,14 @@ function UpgradePrompt({ viewId }) {
|
|
|
854
953
|
" ",
|
|
855
954
|
t(headerKey, { title })
|
|
856
955
|
] }),
|
|
857
|
-
/* @__PURE__ */
|
|
858
|
-
/* @__PURE__ */
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
/* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
865
|
-
" ",
|
|
866
|
-
t(buyUrlKey)
|
|
867
|
-
] }),
|
|
868
|
-
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
869
|
-
/* @__PURE__ */ jsx7(Text6, { color: COLORS.muted, children: t("upgrade_activateWith") }),
|
|
870
|
-
/* @__PURE__ */ jsxs5(Text6, { color: COLORS.success, bold: true, children: [
|
|
871
|
-
" ",
|
|
872
|
-
t("upgrade_activateCmd")
|
|
873
|
-
] }),
|
|
874
|
-
/* @__PURE__ */ jsx7(Text6, { children: " " }),
|
|
875
|
-
/* @__PURE__ */ jsx7(Text6, { color: COLORS.brand, children: t(labelKey) })
|
|
956
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.text, wrap: "wrap", children: t(keys.desc) }),
|
|
957
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", marginTop: SPACING.xs, children: [
|
|
958
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.info, bold: true, children: t(pricingKey) }),
|
|
959
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_buyAt") }),
|
|
960
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.sky, bold: true, children: t(buyUrlKey) }),
|
|
961
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.muted, children: t("upgrade_activateWith") }),
|
|
962
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.success, bold: true, children: t("upgrade_activateCmd") }),
|
|
963
|
+
/* @__PURE__ */ jsx8(Text6, { color: COLORS.brand, children: t(labelKey) })
|
|
876
964
|
] })
|
|
877
965
|
]
|
|
878
966
|
}
|
|
@@ -880,8 +968,20 @@ function UpgradePrompt({ viewId }) {
|
|
|
880
968
|
}
|
|
881
969
|
|
|
882
970
|
// src/views/dashboard.tsx
|
|
883
|
-
import { useEffect as
|
|
884
|
-
import { Box as Box9, Text as Text12
|
|
971
|
+
import { useEffect as useEffect5, useMemo as useMemo2 } from "react";
|
|
972
|
+
import { Box as Box9, Text as Text12 } from "ink";
|
|
973
|
+
|
|
974
|
+
// src/hooks/use-visible-rows.ts
|
|
975
|
+
function useVisibleRows({
|
|
976
|
+
reservedRows,
|
|
977
|
+
fallbackReservedRows = reservedRows,
|
|
978
|
+
minRows = 3
|
|
979
|
+
}) {
|
|
980
|
+
const { height: contentHeight } = useContentSize();
|
|
981
|
+
const { rows: terminalRows } = useTerminalSize();
|
|
982
|
+
const availableRows = contentHeight > 0 ? contentHeight - reservedRows : terminalRows - fallbackReservedRows;
|
|
983
|
+
return Math.max(minRows, Math.floor(availableRows));
|
|
984
|
+
}
|
|
885
985
|
|
|
886
986
|
// src/stores/brew-store.ts
|
|
887
987
|
import { create as create4 } from "zustand";
|
|
@@ -1847,12 +1947,11 @@ var useComplianceStore = create8((set, get) => ({
|
|
|
1847
1947
|
}));
|
|
1848
1948
|
|
|
1849
1949
|
// src/components/common/stat-card.tsx
|
|
1850
|
-
import { Box as Box6, Text as Text7
|
|
1851
|
-
import { jsx as
|
|
1950
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
1951
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1852
1952
|
function StatCard({ label, value, color = COLORS.white }) {
|
|
1853
|
-
const {
|
|
1854
|
-
const
|
|
1855
|
-
const minW = cols < 60 ? 12 : cols < 100 ? 14 : 16;
|
|
1953
|
+
const { columns } = useTerminalSize();
|
|
1954
|
+
const minW = columns < 60 ? 12 : columns < 100 ? 14 : 16;
|
|
1856
1955
|
return /* @__PURE__ */ jsxs6(
|
|
1857
1956
|
Box6,
|
|
1858
1957
|
{
|
|
@@ -1862,10 +1961,11 @@ function StatCard({ label, value, color = COLORS.white }) {
|
|
|
1862
1961
|
paddingY: SPACING.none,
|
|
1863
1962
|
flexDirection: "column",
|
|
1864
1963
|
alignItems: "center",
|
|
1964
|
+
flexShrink: 1,
|
|
1865
1965
|
minWidth: minW,
|
|
1866
1966
|
children: [
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1967
|
+
/* @__PURE__ */ jsx9(Text7, { bold: true, color, children: value }),
|
|
1968
|
+
/* @__PURE__ */ jsx9(Text7, { color: COLORS.muted, children: label })
|
|
1869
1969
|
]
|
|
1870
1970
|
}
|
|
1871
1971
|
);
|
|
@@ -1874,10 +1974,10 @@ function StatCard({ label, value, color = COLORS.white }) {
|
|
|
1874
1974
|
// src/components/common/loading.tsx
|
|
1875
1975
|
import { Box as Box7, Text as Text8 } from "ink";
|
|
1876
1976
|
import { Spinner } from "@inkjs/ui";
|
|
1877
|
-
import { jsx as
|
|
1977
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1878
1978
|
function Loading({ message }) {
|
|
1879
1979
|
useLocaleStore((s) => s.locale);
|
|
1880
|
-
return /* @__PURE__ */
|
|
1980
|
+
return /* @__PURE__ */ jsx10(Box7, { paddingY: SPACING.xs, children: /* @__PURE__ */ jsx10(Spinner, { label: message ?? t("loading_default") }) });
|
|
1881
1981
|
}
|
|
1882
1982
|
function ErrorMessage({ message }) {
|
|
1883
1983
|
useLocaleStore((s) => s.locale);
|
|
@@ -1887,7 +1987,7 @@ function ErrorMessage({ message }) {
|
|
|
1887
1987
|
" ",
|
|
1888
1988
|
t("error_prefix")
|
|
1889
1989
|
] }),
|
|
1890
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsx10(Text8, { color: COLORS.error, children: message })
|
|
1891
1991
|
] });
|
|
1892
1992
|
}
|
|
1893
1993
|
|
|
@@ -1912,14 +2012,14 @@ function StatusBadge({ label, variant }) {
|
|
|
1912
2012
|
|
|
1913
2013
|
// src/components/common/section-header.tsx
|
|
1914
2014
|
import { Box as Box8, Text as Text10 } from "ink";
|
|
1915
|
-
import { jsx as
|
|
2015
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1916
2016
|
function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
|
|
1917
2017
|
return /* @__PURE__ */ jsxs9(Box8, { gap: SPACING.xs, children: [
|
|
1918
2018
|
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
1919
2019
|
emoji,
|
|
1920
2020
|
" "
|
|
1921
2021
|
] }),
|
|
1922
|
-
gradient ? /* @__PURE__ */
|
|
2022
|
+
gradient ? /* @__PURE__ */ jsx11(GradientText, { colors: gradient, bold: true, children: title }) : /* @__PURE__ */ jsx11(Text10, { bold: true, color, children: title }),
|
|
1923
2023
|
count !== void 0 && /* @__PURE__ */ jsxs9(Text10, { color: COLORS.textSecondary, children: [
|
|
1924
2024
|
"(",
|
|
1925
2025
|
count,
|
|
@@ -1930,22 +2030,22 @@ function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
|
|
|
1930
2030
|
|
|
1931
2031
|
// src/components/common/version-arrow.tsx
|
|
1932
2032
|
import { Text as Text11 } from "ink";
|
|
1933
|
-
import { Fragment as Fragment3, jsx as
|
|
2033
|
+
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1934
2034
|
function VersionArrow({ current, latest }) {
|
|
1935
2035
|
return /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
1936
2036
|
/* @__PURE__ */ jsxs10(Text11, { color: COLORS.muted, children: [
|
|
1937
2037
|
t("version_installed"),
|
|
1938
2038
|
" "
|
|
1939
2039
|
] }),
|
|
1940
|
-
/* @__PURE__ */
|
|
1941
|
-
/* @__PURE__ */
|
|
1942
|
-
/* @__PURE__ */
|
|
2040
|
+
/* @__PURE__ */ jsx12(Text11, { color: COLORS.error, children: current }),
|
|
2041
|
+
/* @__PURE__ */ jsx12(Text11, { color: COLORS.warning, children: " \u2500\u2500 " }),
|
|
2042
|
+
/* @__PURE__ */ jsx12(Text11, { color: COLORS.gold, children: "\u25B6" }),
|
|
1943
2043
|
/* @__PURE__ */ jsxs10(Text11, { color: COLORS.muted, children: [
|
|
1944
2044
|
" ",
|
|
1945
2045
|
t("version_available"),
|
|
1946
2046
|
" "
|
|
1947
2047
|
] }),
|
|
1948
|
-
/* @__PURE__ */
|
|
2048
|
+
/* @__PURE__ */ jsx12(Text11, { color: COLORS.teal, children: latest })
|
|
1949
2049
|
] });
|
|
1950
2050
|
}
|
|
1951
2051
|
|
|
@@ -1977,7 +2077,7 @@ function truncate(str, maxLen) {
|
|
|
1977
2077
|
}
|
|
1978
2078
|
|
|
1979
2079
|
// src/views/dashboard.tsx
|
|
1980
|
-
import { jsx as
|
|
2080
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1981
2081
|
function ProStatusPanel() {
|
|
1982
2082
|
const security = useSecurityStore((s) => s.summary);
|
|
1983
2083
|
const drift = useBrewfileStore((s) => s.drift);
|
|
@@ -1990,28 +2090,28 @@ function ProStatusPanel() {
|
|
|
1990
2090
|
const syncAgo = lastSync ? formatRelativeTime(new Date(lastSync).getTime() / 1e3) : null;
|
|
1991
2091
|
const violationCount = complianceReport ? complianceReport.violations.length : null;
|
|
1992
2092
|
return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.none, marginTop: SPACING.xs, children: [
|
|
1993
|
-
/* @__PURE__ */
|
|
2093
|
+
/* @__PURE__ */ jsx13(Text12, { bold: true, color: COLORS.purple, children: t("dashboard_pro_status") }),
|
|
1994
2094
|
/* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
1995
|
-
/* @__PURE__ */
|
|
1996
|
-
cveCount === null ? /* @__PURE__ */
|
|
2095
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_security") }),
|
|
2096
|
+
cveCount === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : cveCount === 0 ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.success, children: t("dashboard_no_cves") }) : /* @__PURE__ */ jsxs11(Text12, { color: COLORS.error, children: [
|
|
1997
2097
|
t("dashboard_cves", { count: String(cveCount) }),
|
|
1998
2098
|
criticalCount && criticalCount > 0 ? ` (${criticalCount} critical)` : ""
|
|
1999
2099
|
] })
|
|
2000
2100
|
] }),
|
|
2001
2101
|
/* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2002
|
-
/* @__PURE__ */
|
|
2003
|
-
driftScore === null ? /* @__PURE__ */
|
|
2102
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_brewfile") }),
|
|
2103
|
+
driftScore === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : /* @__PURE__ */ jsxs11(Text12, { color: driftScore >= 80 ? COLORS.success : COLORS.warning, children: [
|
|
2004
2104
|
driftScore,
|
|
2005
2105
|
"%"
|
|
2006
2106
|
] })
|
|
2007
2107
|
] }),
|
|
2008
2108
|
/* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2009
|
-
/* @__PURE__ */
|
|
2010
|
-
syncAgo === null ? /* @__PURE__ */
|
|
2109
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_sync") }),
|
|
2110
|
+
syncAgo === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_sync_never") }) : /* @__PURE__ */ jsx13(Text12, { color: COLORS.info, children: t("dashboard_sync_ago", { time: syncAgo }) })
|
|
2011
2111
|
] }),
|
|
2012
2112
|
/* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2013
|
-
/* @__PURE__ */
|
|
2014
|
-
violationCount === null ? /* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_compliance") }),
|
|
2114
|
+
violationCount === null ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: "\u2014" }) : violationCount === 0 ? /* @__PURE__ */ jsx13(Text12, { color: COLORS.success, children: t("dashboard_compliance_ok") }) : /* @__PURE__ */ jsx13(Text12, { color: COLORS.warning, children: t("dashboard_compliance_violations", { count: String(violationCount) }) })
|
|
2015
2115
|
] })
|
|
2016
2116
|
] });
|
|
2017
2117
|
}
|
|
@@ -2026,9 +2126,14 @@ function DashboardView() {
|
|
|
2026
2126
|
const lastFetchedAt = useBrewStore((s) => s.lastFetchedAt);
|
|
2027
2127
|
const fetchAll = useBrewStore((s) => s.fetchAll);
|
|
2028
2128
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
2029
|
-
const {
|
|
2030
|
-
const
|
|
2031
|
-
|
|
2129
|
+
const { columns } = useTerminalSize();
|
|
2130
|
+
const splitRows = useVisibleRows({
|
|
2131
|
+
reservedRows: 18,
|
|
2132
|
+
fallbackReservedRows: 22,
|
|
2133
|
+
minRows: 2
|
|
2134
|
+
});
|
|
2135
|
+
const halfRows = Math.max(1, Math.floor(splitRows / 2));
|
|
2136
|
+
useEffect5(() => {
|
|
2032
2137
|
fetchAll();
|
|
2033
2138
|
}, []);
|
|
2034
2139
|
useViewInput((input) => {
|
|
@@ -2053,11 +2158,11 @@ function DashboardView() {
|
|
|
2053
2158
|
const outdatedValue = loading.outdated ? "..." : errors.outdated ? t("dashboard_statError") : outdated.formulae.length + outdated.casks.length;
|
|
2054
2159
|
const servicesValue = loading.services ? "..." : errors.services ? t("dashboard_statError") : `${runningServices}/${services.length}`;
|
|
2055
2160
|
const lastUpdated = lastFetchedAt.installed ? formatRelativeTime(lastFetchedAt.installed / 1e3) : null;
|
|
2056
|
-
if (loading.installed) return /* @__PURE__ */
|
|
2161
|
+
if (loading.installed) return /* @__PURE__ */ jsx13(Loading, { message: t("loading_fetchingBrew") });
|
|
2057
2162
|
if (errors.installed) {
|
|
2058
2163
|
return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", children: [
|
|
2059
|
-
/* @__PURE__ */
|
|
2060
|
-
/* @__PURE__ */
|
|
2164
|
+
/* @__PURE__ */ jsx13(ErrorMessage, { message: errors.installed }),
|
|
2165
|
+
/* @__PURE__ */ jsx13(Box9, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.textSecondary, children: [
|
|
2061
2166
|
"r:",
|
|
2062
2167
|
t("hint_refresh")
|
|
2063
2168
|
] }) })
|
|
@@ -2065,11 +2170,11 @@ function DashboardView() {
|
|
|
2065
2170
|
}
|
|
2066
2171
|
const isNarrow = columns < 60;
|
|
2067
2172
|
return /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", gap: SPACING.sm, children: [
|
|
2068
|
-
/* @__PURE__ */
|
|
2173
|
+
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u{1F4CA}", title: t("dashboard_overview"), gradient: GRADIENTS.gold }),
|
|
2069
2174
|
/* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, flexWrap: "wrap", flexDirection: isNarrow ? "column" : "row", children: [
|
|
2070
|
-
/* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2175
|
+
/* @__PURE__ */ jsx13(StatCard, { label: t("dashboard_formulae"), value: formulae.length, color: COLORS.info }),
|
|
2176
|
+
/* @__PURE__ */ jsx13(StatCard, { label: t("dashboard_casks"), value: casks.length, color: COLORS.purple }),
|
|
2177
|
+
/* @__PURE__ */ jsx13(
|
|
2073
2178
|
StatCard,
|
|
2074
2179
|
{
|
|
2075
2180
|
label: t("dashboard_outdated"),
|
|
@@ -2077,7 +2182,7 @@ function DashboardView() {
|
|
|
2077
2182
|
color: typeof outdatedValue === "number" && outdatedValue > 0 ? COLORS.warning : errors.outdated ? COLORS.error : COLORS.success
|
|
2078
2183
|
}
|
|
2079
2184
|
),
|
|
2080
|
-
/* @__PURE__ */
|
|
2185
|
+
/* @__PURE__ */ jsx13(
|
|
2081
2186
|
StatCard,
|
|
2082
2187
|
{
|
|
2083
2188
|
label: t("dashboard_services"),
|
|
@@ -2086,9 +2191,9 @@ function DashboardView() {
|
|
|
2086
2191
|
}
|
|
2087
2192
|
)
|
|
2088
2193
|
] }),
|
|
2089
|
-
lastUpdated && /* @__PURE__ */
|
|
2194
|
+
lastUpdated && /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_lastUpdated", { time: lastUpdated }) }),
|
|
2090
2195
|
partialErrors.length > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: [
|
|
2091
|
-
/* @__PURE__ */
|
|
2196
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.warning, bold: true, children: t("dashboard_partialData") }),
|
|
2092
2197
|
partialErrors.map((item) => /* @__PURE__ */ jsxs11(Text12, { color: COLORS.muted, children: [
|
|
2093
2198
|
item.label,
|
|
2094
2199
|
": ",
|
|
@@ -2096,56 +2201,59 @@ function DashboardView() {
|
|
|
2096
2201
|
] }, item.label))
|
|
2097
2202
|
] }),
|
|
2098
2203
|
config && !errors.config && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", children: [
|
|
2099
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u2139\uFE0F", title: t("dashboard_systemInfo"), gradient: [COLORS.text, COLORS.muted] }),
|
|
2100
2205
|
/* @__PURE__ */ jsxs11(Box9, { borderStyle: "round", borderColor: COLORS.blue, paddingX: SPACING.sm, paddingY: SPACING.none, flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2101
2206
|
/* @__PURE__ */ jsxs11(Text12, { children: [
|
|
2102
|
-
/* @__PURE__ */
|
|
2207
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_homebrew") }),
|
|
2103
2208
|
" ",
|
|
2104
2209
|
config.HOMEBREW_VERSION
|
|
2105
2210
|
] }),
|
|
2106
2211
|
/* @__PURE__ */ jsxs11(Text12, { children: [
|
|
2107
|
-
/* @__PURE__ */
|
|
2212
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_prefix") }),
|
|
2108
2213
|
" ",
|
|
2109
2214
|
config.HOMEBREW_PREFIX
|
|
2110
2215
|
] }),
|
|
2111
2216
|
/* @__PURE__ */ jsxs11(Text12, { children: [
|
|
2112
|
-
/* @__PURE__ */
|
|
2217
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("dashboard_updated") }),
|
|
2113
2218
|
" ",
|
|
2114
2219
|
config.coreUpdated
|
|
2115
2220
|
] })
|
|
2116
2221
|
] })
|
|
2117
2222
|
] }),
|
|
2118
2223
|
!errors.outdated && outdated.formulae.length > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2119
|
-
/* @__PURE__ */
|
|
2224
|
+
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u{1F4E6}", title: t("dashboard_outdatedPackages"), gradient: GRADIENTS.fire }),
|
|
2120
2225
|
/* @__PURE__ */ jsxs11(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
2121
|
-
outdated.formulae.slice(0,
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2226
|
+
outdated.formulae.slice(0, halfRows).map((pkg) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2227
|
+
/* @__PURE__ */ jsx13(Text12, { color: COLORS.text, children: pkg.name }),
|
|
2228
|
+
/* @__PURE__ */ jsx13(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version })
|
|
2124
2229
|
] }, pkg.name)),
|
|
2125
|
-
outdated.formulae.length >
|
|
2230
|
+
outdated.formulae.length > halfRows && /* @__PURE__ */ jsx13(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: outdated.formulae.length - halfRows }) })
|
|
2126
2231
|
] })
|
|
2127
2232
|
] }),
|
|
2128
2233
|
!errors.services && errorServices > 0 && /* @__PURE__ */ jsxs11(Box9, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2129
|
-
/* @__PURE__ */
|
|
2130
|
-
/* @__PURE__ */
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2234
|
+
/* @__PURE__ */ jsx13(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("dashboard_serviceErrors"), color: COLORS.error }),
|
|
2235
|
+
/* @__PURE__ */ jsxs11(Box9, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
2236
|
+
errorServiceList.slice(0, halfRows).map((s) => /* @__PURE__ */ jsxs11(Box9, { gap: SPACING.xs, children: [
|
|
2237
|
+
/* @__PURE__ */ jsx13(StatusBadge, { label: t("badge_error"), variant: "error" }),
|
|
2238
|
+
/* @__PURE__ */ jsx13(Text12, { children: s.name }),
|
|
2239
|
+
s.exit_code != null && /* @__PURE__ */ jsx13(Text12, { color: COLORS.muted, children: t("common_exit", { code: s.exit_code }) })
|
|
2240
|
+
] }, s.name)),
|
|
2241
|
+
errorServiceList.length > halfRows && /* @__PURE__ */ jsx13(Text12, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: errorServiceList.length - halfRows }) })
|
|
2242
|
+
] })
|
|
2135
2243
|
] }),
|
|
2136
|
-
isPro() && /* @__PURE__ */
|
|
2244
|
+
isPro() && /* @__PURE__ */ jsx13(ProStatusPanel, {})
|
|
2137
2245
|
] });
|
|
2138
2246
|
}
|
|
2139
2247
|
|
|
2140
2248
|
// src/views/installed.tsx
|
|
2141
|
-
import { useState as useState6, useMemo as useMemo3, useEffect as useEffect9, useRef as
|
|
2249
|
+
import { useState as useState6, useMemo as useMemo3, useEffect as useEffect9, useRef as useRef3 } from "react";
|
|
2142
2250
|
import { Box as Box15, Text as Text18 } from "ink";
|
|
2143
2251
|
|
|
2144
2252
|
// src/hooks/use-debounce.ts
|
|
2145
|
-
import { useState as
|
|
2253
|
+
import { useState as useState4, useEffect as useEffect6 } from "react";
|
|
2146
2254
|
function useDebounce(value, delayMs) {
|
|
2147
|
-
const [debounced, setDebounced] =
|
|
2148
|
-
|
|
2255
|
+
const [debounced, setDebounced] = useState4(value);
|
|
2256
|
+
useEffect6(() => {
|
|
2149
2257
|
const timer = setTimeout(() => setDebounced(value), delayMs);
|
|
2150
2258
|
return () => clearTimeout(timer);
|
|
2151
2259
|
}, [value, delayMs]);
|
|
@@ -2153,7 +2261,7 @@ function useDebounce(value, delayMs) {
|
|
|
2153
2261
|
}
|
|
2154
2262
|
|
|
2155
2263
|
// src/hooks/use-brew-stream.ts
|
|
2156
|
-
import { useState as
|
|
2264
|
+
import { useState as useState5, useCallback, useRef as useRef2, useEffect as useEffect7 } from "react";
|
|
2157
2265
|
var MAX_LINES = 100;
|
|
2158
2266
|
async function logToHistory(args, success, error) {
|
|
2159
2267
|
const detected = detectAction(args);
|
|
@@ -2166,13 +2274,13 @@ async function logToHistory(args, success, error) {
|
|
|
2166
2274
|
}
|
|
2167
2275
|
}
|
|
2168
2276
|
function useBrewStream() {
|
|
2169
|
-
const [lines, setLines] =
|
|
2170
|
-
const [isRunning, setIsRunning] =
|
|
2171
|
-
const [error, setError2] =
|
|
2172
|
-
const cancelRef =
|
|
2173
|
-
const generatorRef =
|
|
2174
|
-
const mountedRef =
|
|
2175
|
-
|
|
2277
|
+
const [lines, setLines] = useState5([]);
|
|
2278
|
+
const [isRunning, setIsRunning] = useState5(false);
|
|
2279
|
+
const [error, setError2] = useState5(null);
|
|
2280
|
+
const cancelRef = useRef2(false);
|
|
2281
|
+
const generatorRef = useRef2(null);
|
|
2282
|
+
const mountedRef = useRef2(true);
|
|
2283
|
+
useEffect7(() => {
|
|
2176
2284
|
mountedRef.current = true;
|
|
2177
2285
|
return () => {
|
|
2178
2286
|
mountedRef.current = false;
|
|
@@ -2232,7 +2340,7 @@ function useBrewStream() {
|
|
|
2232
2340
|
// src/components/common/search-input.tsx
|
|
2233
2341
|
import { Box as Box10, Text as Text13 } from "ink";
|
|
2234
2342
|
import { TextInput } from "@inkjs/ui";
|
|
2235
|
-
import { jsx as
|
|
2343
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2236
2344
|
function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
|
|
2237
2345
|
const resolvedPlaceholder = placeholder ?? t("searchInput_placeholder");
|
|
2238
2346
|
return /* @__PURE__ */ jsxs12(Box10, { children: [
|
|
@@ -2240,25 +2348,25 @@ function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
|
|
|
2240
2348
|
"\u{1F50D}",
|
|
2241
2349
|
" "
|
|
2242
2350
|
] }),
|
|
2243
|
-
isActive ? /* @__PURE__ */
|
|
2351
|
+
isActive ? /* @__PURE__ */ jsx14(
|
|
2244
2352
|
TextInput,
|
|
2245
2353
|
{
|
|
2246
2354
|
placeholder: resolvedPlaceholder,
|
|
2247
2355
|
defaultValue,
|
|
2248
2356
|
onChange
|
|
2249
2357
|
}
|
|
2250
|
-
) : /* @__PURE__ */
|
|
2358
|
+
) : /* @__PURE__ */ jsx14(Text13, { color: COLORS.textSecondary, children: defaultValue || placeholder })
|
|
2251
2359
|
] });
|
|
2252
2360
|
}
|
|
2253
2361
|
|
|
2254
2362
|
// src/components/common/confirm-dialog.tsx
|
|
2255
|
-
import { useEffect as
|
|
2363
|
+
import { useEffect as useEffect8 } from "react";
|
|
2256
2364
|
import { Box as Box11, Text as Text14, useInput as useInput3 } from "ink";
|
|
2257
|
-
import { jsx as
|
|
2365
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2258
2366
|
function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
2259
2367
|
const locale = useLocaleStore((s) => s.locale);
|
|
2260
2368
|
const { openModal, closeModal } = useModalStore();
|
|
2261
|
-
|
|
2369
|
+
useEffect8(() => {
|
|
2262
2370
|
openModal();
|
|
2263
2371
|
return () => {
|
|
2264
2372
|
closeModal();
|
|
@@ -2270,12 +2378,12 @@ function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
|
2270
2378
|
else if (input === "n" || input === "N") onCancel();
|
|
2271
2379
|
else if (key.escape) onCancel();
|
|
2272
2380
|
});
|
|
2273
|
-
return /* @__PURE__ */ jsxs13(Box11, { borderStyle: "double", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.xs, flexDirection: "column", children: [
|
|
2274
|
-
/* @__PURE__ */
|
|
2381
|
+
return /* @__PURE__ */ jsxs13(Box11, { borderStyle: "double", borderColor: COLORS.purple, paddingX: SPACING.sm, paddingY: SPACING.xs, flexDirection: "column", flexShrink: 1, children: [
|
|
2382
|
+
/* @__PURE__ */ jsx15(Text14, { bold: true, color: COLORS.text, wrap: "wrap", children: message }),
|
|
2275
2383
|
/* @__PURE__ */ jsxs13(Box11, { marginTop: SPACING.xs, children: [
|
|
2276
|
-
/* @__PURE__ */
|
|
2277
|
-
/* @__PURE__ */
|
|
2278
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx15(Text14, { color: COLORS.success, children: t("confirm_yes") }),
|
|
2385
|
+
/* @__PURE__ */ jsx15(Text14, { children: " / " }),
|
|
2386
|
+
/* @__PURE__ */ jsx15(Text14, { color: COLORS.error, children: t("confirm_no") })
|
|
2279
2387
|
] })
|
|
2280
2388
|
] });
|
|
2281
2389
|
}
|
|
@@ -2283,13 +2391,13 @@ function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
|
2283
2391
|
// src/components/common/progress-log.tsx
|
|
2284
2392
|
import { Box as Box12, Text as Text15 } from "ink";
|
|
2285
2393
|
import { Spinner as Spinner2 } from "@inkjs/ui";
|
|
2286
|
-
import { jsx as
|
|
2394
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2287
2395
|
function ProgressLog({ lines, isRunning, title, maxVisible = 15 }) {
|
|
2288
2396
|
const start = Math.max(0, lines.length - maxVisible);
|
|
2289
2397
|
const visible = lines.slice(start);
|
|
2290
2398
|
return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.sky, paddingX: SPACING.xs, children: [
|
|
2291
2399
|
title && /* @__PURE__ */ jsxs14(Box12, { marginBottom: SPACING.xs, children: [
|
|
2292
|
-
isRunning && /* @__PURE__ */
|
|
2400
|
+
isRunning && /* @__PURE__ */ jsx16(Spinner2, { label: "" }),
|
|
2293
2401
|
/* @__PURE__ */ jsxs14(Text15, { bold: true, color: COLORS.sky, children: [
|
|
2294
2402
|
" ",
|
|
2295
2403
|
title
|
|
@@ -2299,15 +2407,15 @@ function ProgressLog({ lines, isRunning, title, maxVisible = 15 }) {
|
|
|
2299
2407
|
// UI-006: keys are absolute indices, so a line that scrolls off-screen
|
|
2300
2408
|
// does not change the key of remaining lines. Stable identity prevents
|
|
2301
2409
|
// React from treating the whole list as new on every append.
|
|
2302
|
-
/* @__PURE__ */
|
|
2410
|
+
/* @__PURE__ */ jsx16(Text15, { color: COLORS.muted, wrap: "wrap", children: line }, `log-${start + i}`)
|
|
2303
2411
|
)),
|
|
2304
|
-
lines.length === 0 && !isRunning && /* @__PURE__ */
|
|
2412
|
+
lines.length === 0 && !isRunning && /* @__PURE__ */ jsx16(Text15, { color: COLORS.textSecondary, italic: true, children: t("progress_noOutput") })
|
|
2305
2413
|
] });
|
|
2306
2414
|
}
|
|
2307
2415
|
|
|
2308
2416
|
// src/components/common/result-banner.tsx
|
|
2309
2417
|
import { Box as Box13, Text as Text16 } from "ink";
|
|
2310
|
-
import { jsx as
|
|
2418
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2311
2419
|
var STATUS_COLORS = {
|
|
2312
2420
|
success: COLORS.success,
|
|
2313
2421
|
error: COLORS.error,
|
|
@@ -2315,64 +2423,21 @@ var STATUS_COLORS = {
|
|
|
2315
2423
|
info: COLORS.info
|
|
2316
2424
|
};
|
|
2317
2425
|
function ResultBanner({ status, message }) {
|
|
2318
|
-
return /* @__PURE__ */
|
|
2426
|
+
return /* @__PURE__ */ jsx17(Box13, { borderStyle: "round", borderColor: STATUS_COLORS[status], paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx17(Text16, { color: STATUS_COLORS[status], bold: true, children: message }) });
|
|
2319
2427
|
}
|
|
2320
2428
|
|
|
2321
2429
|
// src/components/common/selectable-row.tsx
|
|
2322
2430
|
import { Box as Box14, Text as Text17 } from "ink";
|
|
2323
|
-
import { jsx as
|
|
2431
|
+
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2324
2432
|
function SelectableRow({ isCurrent, children, gap = 1 }) {
|
|
2325
2433
|
return /* @__PURE__ */ jsxs15(Box14, { gap, children: [
|
|
2326
|
-
/* @__PURE__ */
|
|
2434
|
+
/* @__PURE__ */ jsx18(Text17, { color: isCurrent ? COLORS.success : COLORS.muted, children: isCurrent ? "\u25B6" : " " }),
|
|
2327
2435
|
children
|
|
2328
2436
|
] });
|
|
2329
2437
|
}
|
|
2330
2438
|
|
|
2331
|
-
// src/hooks/use-container-size.ts
|
|
2332
|
-
import { useEffect as useEffect8, useState as useState5 } from "react";
|
|
2333
|
-
import { measureElement } from "ink";
|
|
2334
|
-
|
|
2335
|
-
// src/hooks/use-terminal-size.ts
|
|
2336
|
-
import { useEffect as useEffect7, useState as useState4 } from "react";
|
|
2337
|
-
import { useStdout as useStdout4 } from "ink";
|
|
2338
|
-
function useTerminalSize() {
|
|
2339
|
-
const { stdout } = useStdout4();
|
|
2340
|
-
const [size, setSize] = useState4(() => ({
|
|
2341
|
-
columns: stdout?.columns ?? 80,
|
|
2342
|
-
rows: stdout?.rows ?? 24
|
|
2343
|
-
}));
|
|
2344
|
-
useEffect7(() => {
|
|
2345
|
-
if (!stdout) return;
|
|
2346
|
-
const onResize = () => {
|
|
2347
|
-
setSize({
|
|
2348
|
-
columns: stdout.columns ?? 80,
|
|
2349
|
-
rows: stdout.rows ?? 24
|
|
2350
|
-
});
|
|
2351
|
-
};
|
|
2352
|
-
stdout.on("resize", onResize);
|
|
2353
|
-
return () => {
|
|
2354
|
-
stdout.off("resize", onResize);
|
|
2355
|
-
};
|
|
2356
|
-
}, [stdout]);
|
|
2357
|
-
return size;
|
|
2358
|
-
}
|
|
2359
|
-
|
|
2360
|
-
// src/hooks/use-container-size.ts
|
|
2361
|
-
function useContainerSize(ref) {
|
|
2362
|
-
const terminal = useTerminalSize();
|
|
2363
|
-
const [size, setSize] = useState5({ width: 0, height: 0 });
|
|
2364
|
-
useEffect8(() => {
|
|
2365
|
-
if (!ref.current) return;
|
|
2366
|
-
const measured = measureElement(ref.current);
|
|
2367
|
-
setSize(
|
|
2368
|
-
(prev) => prev.width === measured.width && prev.height === measured.height ? prev : measured
|
|
2369
|
-
);
|
|
2370
|
-
}, [ref, terminal.columns, terminal.rows]);
|
|
2371
|
-
return size;
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
2439
|
// src/views/installed.tsx
|
|
2375
|
-
import { jsx as
|
|
2440
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2376
2441
|
function InstalledView() {
|
|
2377
2442
|
const formulae = useBrewStore((s) => s.formulae);
|
|
2378
2443
|
const casks = useBrewStore((s) => s.casks);
|
|
@@ -2382,12 +2447,12 @@ function InstalledView() {
|
|
|
2382
2447
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
2383
2448
|
const selectPackage = useNavigationStore((s) => s.selectPackage);
|
|
2384
2449
|
const { openModal, closeModal } = useModalStore();
|
|
2385
|
-
const containerRef =
|
|
2450
|
+
const containerRef = useRef3(null);
|
|
2386
2451
|
const { width: containerWidth } = useContainerSize(containerRef);
|
|
2387
|
-
const { rows: terminalRows } = useTerminalSize();
|
|
2388
2452
|
const columns = containerWidth > 0 ? containerWidth : 80;
|
|
2389
|
-
const nameWidth = Math.floor(columns * 0.35);
|
|
2390
|
-
const versionWidth = Math.floor(columns * 0.15);
|
|
2453
|
+
const nameWidth = Math.max(12, Math.floor(columns * 0.35));
|
|
2454
|
+
const versionWidth = Math.max(8, Math.floor(columns * 0.15));
|
|
2455
|
+
const descWidth = Math.max(10, columns - nameWidth - versionWidth - 8);
|
|
2391
2456
|
const [filter, setFilter] = useState6("");
|
|
2392
2457
|
const [cursor, setCursor] = useState6(0);
|
|
2393
2458
|
const [tab, setTab] = useState6("formulae");
|
|
@@ -2395,6 +2460,16 @@ function InstalledView() {
|
|
|
2395
2460
|
const [confirmUninstall, setConfirmUninstall] = useState6(null);
|
|
2396
2461
|
const debouncedFilter = useDebounce(filter, 200);
|
|
2397
2462
|
const stream = useBrewStream();
|
|
2463
|
+
const listRows = useVisibleRows({
|
|
2464
|
+
reservedRows: isSearching ? 14 : 10,
|
|
2465
|
+
fallbackReservedRows: isSearching ? 18 : 14,
|
|
2466
|
+
minRows: 1
|
|
2467
|
+
});
|
|
2468
|
+
const streamRows = useVisibleRows({
|
|
2469
|
+
reservedRows: 5,
|
|
2470
|
+
fallbackReservedRows: 14,
|
|
2471
|
+
minRows: 1
|
|
2472
|
+
});
|
|
2398
2473
|
useEffect9(() => {
|
|
2399
2474
|
fetchInstalled();
|
|
2400
2475
|
}, []);
|
|
@@ -2459,16 +2534,17 @@ function InstalledView() {
|
|
|
2459
2534
|
setCursor(0);
|
|
2460
2535
|
}
|
|
2461
2536
|
}, { isActive: true });
|
|
2462
|
-
if (loading.installed) return /* @__PURE__ */
|
|
2463
|
-
if (errors.installed) return /* @__PURE__ */
|
|
2537
|
+
if (loading.installed) return /* @__PURE__ */ jsx19(Loading, { message: t("loading_installed") });
|
|
2538
|
+
if (errors.installed) return /* @__PURE__ */ jsx19(ErrorMessage, { message: errors.installed });
|
|
2464
2539
|
if (stream.isRunning || stream.lines.length > 0) {
|
|
2465
2540
|
return /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
|
|
2466
|
-
/* @__PURE__ */
|
|
2541
|
+
/* @__PURE__ */ jsx19(
|
|
2467
2542
|
ProgressLog,
|
|
2468
2543
|
{
|
|
2469
2544
|
lines: stream.lines,
|
|
2470
2545
|
isRunning: stream.isRunning,
|
|
2471
|
-
title: t("pkgInfo_uninstalling", { name: "..." })
|
|
2546
|
+
title: t("pkgInfo_uninstalling", { name: "..." }),
|
|
2547
|
+
maxVisible: streamRows
|
|
2472
2548
|
}
|
|
2473
2549
|
),
|
|
2474
2550
|
stream.isRunning && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, children: [
|
|
@@ -2476,7 +2552,7 @@ function InstalledView() {
|
|
|
2476
2552
|
t("hint_cancel")
|
|
2477
2553
|
] }),
|
|
2478
2554
|
!stream.isRunning && /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2479
|
-
/* @__PURE__ */
|
|
2555
|
+
/* @__PURE__ */ jsx19(
|
|
2480
2556
|
ResultBanner,
|
|
2481
2557
|
{
|
|
2482
2558
|
status: stream.error ? "error" : "success",
|
|
@@ -2490,12 +2566,12 @@ function InstalledView() {
|
|
|
2490
2566
|
] })
|
|
2491
2567
|
] });
|
|
2492
2568
|
}
|
|
2493
|
-
const MAX_VISIBLE_ROWS =
|
|
2569
|
+
const MAX_VISIBLE_ROWS = listRows;
|
|
2494
2570
|
const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
|
|
2495
2571
|
const visible = allItems.slice(start, start + MAX_VISIBLE_ROWS);
|
|
2496
2572
|
return /* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", ref: containerRef, children: [
|
|
2497
2573
|
/* @__PURE__ */ jsxs16(Box15, { marginBottom: SPACING.xs, gap: SPACING.xs, children: [
|
|
2498
|
-
/* @__PURE__ */
|
|
2574
|
+
/* @__PURE__ */ jsx19(
|
|
2499
2575
|
Box15,
|
|
2500
2576
|
{
|
|
2501
2577
|
borderStyle: "round",
|
|
@@ -2508,7 +2584,7 @@ function InstalledView() {
|
|
|
2508
2584
|
] })
|
|
2509
2585
|
}
|
|
2510
2586
|
),
|
|
2511
|
-
/* @__PURE__ */
|
|
2587
|
+
/* @__PURE__ */ jsx19(
|
|
2512
2588
|
Box15,
|
|
2513
2589
|
{
|
|
2514
2590
|
borderStyle: "round",
|
|
@@ -2522,7 +2598,7 @@ function InstalledView() {
|
|
|
2522
2598
|
}
|
|
2523
2599
|
)
|
|
2524
2600
|
] }),
|
|
2525
|
-
confirmUninstall && /* @__PURE__ */
|
|
2601
|
+
confirmUninstall && /* @__PURE__ */ jsx19(
|
|
2526
2602
|
ConfirmDialog,
|
|
2527
2603
|
{
|
|
2528
2604
|
message: t("installed_confirmUninstall", { name: confirmUninstall }),
|
|
@@ -2536,17 +2612,17 @@ function InstalledView() {
|
|
|
2536
2612
|
onCancel: () => setConfirmUninstall(null)
|
|
2537
2613
|
}
|
|
2538
2614
|
),
|
|
2539
|
-
isSearching && /* @__PURE__ */
|
|
2615
|
+
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 }) }),
|
|
2540
2616
|
/* @__PURE__ */ jsxs16(Box15, { gap: SPACING.xs, borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: COLORS.border, children: [
|
|
2541
2617
|
/* @__PURE__ */ jsxs16(Text18, { color: COLORS.text, bold: true, children: [
|
|
2542
2618
|
" ",
|
|
2543
2619
|
t("installed_col_package").padEnd(nameWidth)
|
|
2544
2620
|
] }),
|
|
2545
|
-
/* @__PURE__ */
|
|
2546
|
-
/* @__PURE__ */
|
|
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") })
|
|
2547
2623
|
] }),
|
|
2548
2624
|
/* @__PURE__ */ jsxs16(Box15, { flexDirection: "column", children: [
|
|
2549
|
-
visible.length === 0 && /* @__PURE__ */
|
|
2625
|
+
visible.length === 0 && /* @__PURE__ */ jsx19(Box15, { paddingY: SPACING.xs, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, italic: true, children: t("installed_noPackages") }) }),
|
|
2550
2626
|
start > 0 && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2551
2627
|
" ",
|
|
2552
2628
|
t("scroll_moreAbove", { count: start })
|
|
@@ -2555,13 +2631,13 @@ function InstalledView() {
|
|
|
2555
2631
|
const idx = start + i;
|
|
2556
2632
|
const isCurrent = idx === cursor;
|
|
2557
2633
|
return /* @__PURE__ */ jsxs16(SelectableRow, { isCurrent, children: [
|
|
2558
|
-
/* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
item.outdated && /* @__PURE__ */
|
|
2561
|
-
item.pinned && /* @__PURE__ */
|
|
2562
|
-
item.kegOnly && /* @__PURE__ */
|
|
2563
|
-
item.installedAsDependency && /* @__PURE__ */
|
|
2564
|
-
!item.outdated && !item.pinned && !item.kegOnly && !item.installedAsDependency && /* @__PURE__ */
|
|
2634
|
+
/* @__PURE__ */ jsx19(Text18, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: truncate(item.name, nameWidth).padEnd(nameWidth) }),
|
|
2635
|
+
/* @__PURE__ */ jsx19(Text18, { color: COLORS.teal, children: item.version.padEnd(versionWidth) }),
|
|
2636
|
+
item.outdated && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
|
|
2637
|
+
item.pinned && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
|
|
2638
|
+
item.kegOnly && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
|
|
2639
|
+
item.installedAsDependency && /* @__PURE__ */ jsx19(StatusBadge, { label: t("badge_dep"), variant: "muted" }),
|
|
2640
|
+
!item.outdated && !item.pinned && !item.kegOnly && !item.installedAsDependency && /* @__PURE__ */ jsx19(Text18, { color: COLORS.textSecondary, dimColor: true, children: truncate(item.desc, descWidth) })
|
|
2565
2641
|
] }, item.name);
|
|
2566
2642
|
}),
|
|
2567
2643
|
start + MAX_VISIBLE_ROWS < allItems.length && /* @__PURE__ */ jsxs16(Text18, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -2569,15 +2645,15 @@ function InstalledView() {
|
|
|
2569
2645
|
t("scroll_moreBelow", { count: allItems.length - start - MAX_VISIBLE_ROWS })
|
|
2570
2646
|
] })
|
|
2571
2647
|
] }),
|
|
2572
|
-
/* @__PURE__ */
|
|
2648
|
+
/* @__PURE__ */ jsx19(Box15, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx19(Text18, { color: COLORS.text, bold: true, children: allItems.length > 0 ? `${cursor + 1}/${allItems.length}` : "0/0" }) })
|
|
2573
2649
|
] });
|
|
2574
2650
|
}
|
|
2575
2651
|
|
|
2576
2652
|
// src/views/search.tsx
|
|
2577
|
-
import { useState as useState7, useCallback as useCallback2, useEffect as useEffect10, useRef as
|
|
2653
|
+
import { useState as useState7, useCallback as useCallback2, useEffect as useEffect10, useRef as useRef4 } from "react";
|
|
2578
2654
|
import { Box as Box16, Text as Text19 } from "ink";
|
|
2579
2655
|
import { TextInput as TextInput2 } from "@inkjs/ui";
|
|
2580
|
-
import { jsx as
|
|
2656
|
+
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2581
2657
|
function SearchView() {
|
|
2582
2658
|
const [query, setQuery] = useState7("");
|
|
2583
2659
|
const [results, setResults] = useState7(null);
|
|
@@ -2590,7 +2666,17 @@ function SearchView() {
|
|
|
2590
2666
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
2591
2667
|
const selectPackage = useNavigationStore((s) => s.selectPackage);
|
|
2592
2668
|
const fetchInstalled = useBrewStore((s) => s.fetchInstalled);
|
|
2593
|
-
const hasRefreshed =
|
|
2669
|
+
const hasRefreshed = useRef4(false);
|
|
2670
|
+
const resultRows = useVisibleRows({
|
|
2671
|
+
reservedRows: searchError ? 8 : 6,
|
|
2672
|
+
fallbackReservedRows: searchError ? 18 : 16,
|
|
2673
|
+
minRows: 1
|
|
2674
|
+
});
|
|
2675
|
+
const streamRows = useVisibleRows({
|
|
2676
|
+
reservedRows: 5,
|
|
2677
|
+
fallbackReservedRows: 14,
|
|
2678
|
+
minRows: 1
|
|
2679
|
+
});
|
|
2594
2680
|
useEffect10(() => {
|
|
2595
2681
|
if (results !== null) {
|
|
2596
2682
|
openModal();
|
|
@@ -2625,10 +2711,18 @@ function SearchView() {
|
|
|
2625
2711
|
void fetchInstalled();
|
|
2626
2712
|
}
|
|
2627
2713
|
}, [stream.isRunning, stream.error]);
|
|
2628
|
-
const
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2714
|
+
const allResults = results ? [
|
|
2715
|
+
...results.formulae.map((name) => ({ name, type: "formula" })),
|
|
2716
|
+
...results.casks.map((name) => ({ name, type: "cask" }))
|
|
2717
|
+
] : [];
|
|
2718
|
+
const start = Math.min(
|
|
2719
|
+
Math.max(0, cursor - Math.floor(resultRows / 2)),
|
|
2720
|
+
Math.max(0, allResults.length - resultRows)
|
|
2721
|
+
);
|
|
2722
|
+
const visibleResults = allResults.slice(start, start + resultRows);
|
|
2723
|
+
useEffect10(() => {
|
|
2724
|
+
setCursor((current) => Math.min(current, Math.max(0, allResults.length - 1)));
|
|
2725
|
+
}, [allResults.length]);
|
|
2632
2726
|
useViewInput((input, key) => {
|
|
2633
2727
|
if (stream.isRunning) {
|
|
2634
2728
|
if (key.escape) stream.cancel();
|
|
@@ -2645,17 +2739,18 @@ function SearchView() {
|
|
|
2645
2739
|
void doSearch(query);
|
|
2646
2740
|
return;
|
|
2647
2741
|
}
|
|
2648
|
-
if (key.return &&
|
|
2649
|
-
|
|
2742
|
+
if (key.return && allResults[cursor]) {
|
|
2743
|
+
const result = allResults[cursor];
|
|
2744
|
+
selectPackage(result.name, result.type);
|
|
2650
2745
|
navigate("package-info");
|
|
2651
2746
|
return;
|
|
2652
2747
|
}
|
|
2653
|
-
if ((input === "i" || input === "1") &&
|
|
2654
|
-
setConfirmInstall(
|
|
2748
|
+
if ((input === "i" || input === "1") && allResults[cursor]) {
|
|
2749
|
+
setConfirmInstall(allResults[cursor].name);
|
|
2655
2750
|
return;
|
|
2656
2751
|
}
|
|
2657
2752
|
if (input === "j" || key.downArrow) {
|
|
2658
|
-
setCursor((c) => Math.min(c + 1, Math.max(0,
|
|
2753
|
+
setCursor((c) => Math.min(c + 1, Math.max(0, allResults.length - 1)));
|
|
2659
2754
|
} else if (input === "k" || key.upArrow) {
|
|
2660
2755
|
setCursor((c) => Math.max(c - 1, 0));
|
|
2661
2756
|
} else if (key.escape) {
|
|
@@ -2665,12 +2760,13 @@ function SearchView() {
|
|
|
2665
2760
|
});
|
|
2666
2761
|
if (stream.isRunning || stream.lines.length > 0) {
|
|
2667
2762
|
return /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
|
|
2668
|
-
/* @__PURE__ */
|
|
2763
|
+
/* @__PURE__ */ jsx20(
|
|
2669
2764
|
ProgressLog,
|
|
2670
2765
|
{
|
|
2671
2766
|
lines: stream.lines,
|
|
2672
2767
|
isRunning: stream.isRunning,
|
|
2673
|
-
title: t("search_installing")
|
|
2768
|
+
title: t("search_installing"),
|
|
2769
|
+
maxVisible: streamRows
|
|
2674
2770
|
}
|
|
2675
2771
|
),
|
|
2676
2772
|
stream.isRunning && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, children: [
|
|
@@ -2678,7 +2774,7 @@ function SearchView() {
|
|
|
2678
2774
|
t("hint_cancel")
|
|
2679
2775
|
] }),
|
|
2680
2776
|
!stream.isRunning && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2681
|
-
/* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ jsx20(
|
|
2682
2778
|
ResultBanner,
|
|
2683
2779
|
{
|
|
2684
2780
|
status: stream.error ? "error" : "success",
|
|
@@ -2698,7 +2794,7 @@ function SearchView() {
|
|
|
2698
2794
|
"\u{1F50D}",
|
|
2699
2795
|
" "
|
|
2700
2796
|
] }),
|
|
2701
|
-
!results ? /* @__PURE__ */
|
|
2797
|
+
!results ? /* @__PURE__ */ jsx20(
|
|
2702
2798
|
TextInput2,
|
|
2703
2799
|
{
|
|
2704
2800
|
placeholder: t("search_placeholder"),
|
|
@@ -2709,14 +2805,14 @@ function SearchView() {
|
|
|
2709
2805
|
) : /* @__PURE__ */ jsxs17(Text19, { children: [
|
|
2710
2806
|
t("search_resultsFor"),
|
|
2711
2807
|
' "',
|
|
2712
|
-
/* @__PURE__ */
|
|
2808
|
+
/* @__PURE__ */ jsx20(Text19, { bold: true, color: COLORS.text, children: query }),
|
|
2713
2809
|
'" ',
|
|
2714
|
-
/* @__PURE__ */
|
|
2810
|
+
/* @__PURE__ */ jsx20(Text19, { color: COLORS.textSecondary, children: t("search_escToClear") })
|
|
2715
2811
|
] })
|
|
2716
2812
|
] }),
|
|
2717
|
-
searching && /* @__PURE__ */
|
|
2718
|
-
searchError && /* @__PURE__ */
|
|
2719
|
-
confirmInstall && /* @__PURE__ */
|
|
2813
|
+
searching && /* @__PURE__ */ jsx20(Loading, { message: t("loading_searching") }),
|
|
2814
|
+
searchError && /* @__PURE__ */ jsx20(Box16, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.error, children: searchError }) }),
|
|
2815
|
+
confirmInstall && /* @__PURE__ */ jsx20(
|
|
2720
2816
|
ConfirmDialog,
|
|
2721
2817
|
{
|
|
2722
2818
|
message: t("search_confirmInstall", { name: confirmInstall }),
|
|
@@ -2730,39 +2826,45 @@ function SearchView() {
|
|
|
2730
2826
|
}
|
|
2731
2827
|
),
|
|
2732
2828
|
results && !searching && !confirmInstall && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
return /* @__PURE__ */ jsx19(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx19(Text19, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
|
|
2738
|
-
}),
|
|
2739
|
-
results.formulae.length > MAX_VISIBLE && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2740
|
-
" ",
|
|
2741
|
-
t("scroll_moreBelow", { count: results.formulae.length - MAX_VISIBLE })
|
|
2742
|
-
] })
|
|
2829
|
+
allResults.length > 0 && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, children: [
|
|
2830
|
+
t("search_formulaeHeader", { count: results.formulae.length }),
|
|
2831
|
+
" ",
|
|
2832
|
+
t("search_casksHeader", { count: results.casks.length })
|
|
2743
2833
|
] }),
|
|
2744
|
-
|
|
2745
|
-
/* @__PURE__ */
|
|
2746
|
-
|
|
2747
|
-
|
|
2834
|
+
allResults.length > 0 && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", children: [
|
|
2835
|
+
start > 0 && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2836
|
+
" ",
|
|
2837
|
+
t("scroll_moreAbove", { count: start })
|
|
2838
|
+
] }),
|
|
2839
|
+
visibleResults.map((result, i) => {
|
|
2840
|
+
const idx = start + i;
|
|
2748
2841
|
const isCurrent = idx === cursor;
|
|
2749
|
-
return /* @__PURE__ */
|
|
2842
|
+
return /* @__PURE__ */ jsxs17(SelectableRow, { isCurrent, children: [
|
|
2843
|
+
/* @__PURE__ */ jsx20(Text19, { bold: isCurrent, inverse: isCurrent, children: result.name }),
|
|
2844
|
+
/* @__PURE__ */ jsx20(
|
|
2845
|
+
StatusBadge,
|
|
2846
|
+
{
|
|
2847
|
+
label: result.type === "formula" ? "Formula" : "Cask",
|
|
2848
|
+
variant: result.type === "formula" ? "info" : "muted"
|
|
2849
|
+
}
|
|
2850
|
+
)
|
|
2851
|
+
] }, `${result.type}:${result.name}`);
|
|
2750
2852
|
}),
|
|
2751
|
-
|
|
2853
|
+
start + resultRows < allResults.length && /* @__PURE__ */ jsxs17(Text19, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2752
2854
|
" ",
|
|
2753
|
-
t("scroll_moreBelow", { count:
|
|
2855
|
+
t("scroll_moreBelow", { count: allResults.length - start - resultRows })
|
|
2754
2856
|
] })
|
|
2755
2857
|
] }),
|
|
2756
|
-
|
|
2757
|
-
/* @__PURE__ */
|
|
2858
|
+
allResults.length === 0 && /* @__PURE__ */ jsx20(Box16, { borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.textSecondary, italic: true, children: t("search_noResults") }) }),
|
|
2859
|
+
/* @__PURE__ */ jsx20(Box16, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx20(Text19, { color: COLORS.text, bold: true, children: allResults.length > 0 ? `${cursor + 1}/${allResults.length}` : "" }) })
|
|
2758
2860
|
] })
|
|
2759
2861
|
] });
|
|
2760
2862
|
}
|
|
2761
2863
|
|
|
2762
2864
|
// src/views/outdated.tsx
|
|
2763
|
-
import { useEffect as useEffect11, useMemo as useMemo4, useRef as
|
|
2865
|
+
import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef5, useState as useState8 } from "react";
|
|
2764
2866
|
import { Box as Box17, Text as Text20 } from "ink";
|
|
2765
|
-
import { jsx as
|
|
2867
|
+
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2766
2868
|
function ImpactPanel({ impact }) {
|
|
2767
2869
|
const riskColor = impact.risk === "high" ? COLORS.error : impact.risk === "medium" ? COLORS.warning : COLORS.success;
|
|
2768
2870
|
const riskLabel = impact.risk === "high" ? t("impact_high") : impact.risk === "medium" ? t("impact_medium") : t("impact_low");
|
|
@@ -2779,9 +2881,9 @@ function ImpactPanel({ impact }) {
|
|
|
2779
2881
|
t("impact_affects", { count: impact.reverseDeps.length })
|
|
2780
2882
|
] })
|
|
2781
2883
|
] }),
|
|
2782
|
-
impact.riskReasons.length > 0 && /* @__PURE__ */
|
|
2783
|
-
impact.reverseDeps.length > 0 && impact.reverseDeps.length <= 5 && /* @__PURE__ */
|
|
2784
|
-
impact.risk === "high" && /* @__PURE__ */
|
|
2884
|
+
impact.riskReasons.length > 0 && /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: impact.riskReasons.join(" \xB7 ") }),
|
|
2885
|
+
impact.reverseDeps.length > 0 && impact.reverseDeps.length <= 5 && /* @__PURE__ */ jsx21(Text20, { color: COLORS.muted, dimColor: true, children: t("impact_usedBy", { packages: impact.reverseDeps.join(", ") }) }),
|
|
2886
|
+
impact.risk === "high" && /* @__PURE__ */ jsx21(Text20, { color: COLORS.info, children: t("impact_brewfile_hint") })
|
|
2785
2887
|
] });
|
|
2786
2888
|
}
|
|
2787
2889
|
function OutdatedView() {
|
|
@@ -2789,10 +2891,20 @@ function OutdatedView() {
|
|
|
2789
2891
|
const stream = useBrewStream();
|
|
2790
2892
|
const [cursor, setCursor] = useState8(0);
|
|
2791
2893
|
const [confirmAction, setConfirmAction] = useState8(null);
|
|
2792
|
-
const hasRefreshed =
|
|
2793
|
-
const pendingUpgradeRef =
|
|
2894
|
+
const hasRefreshed = useRef5(false);
|
|
2895
|
+
const pendingUpgradeRef = useRef5(null);
|
|
2794
2896
|
const [impact, setImpact] = useState8(null);
|
|
2795
2897
|
const [impactLoading, setImpactLoading] = useState8(false);
|
|
2898
|
+
const listRows = useVisibleRows({
|
|
2899
|
+
reservedRows: impact || impactLoading ? 11 : 7,
|
|
2900
|
+
fallbackReservedRows: impact || impactLoading ? 18 : 14,
|
|
2901
|
+
minRows: 1
|
|
2902
|
+
});
|
|
2903
|
+
const streamRows = useVisibleRows({
|
|
2904
|
+
reservedRows: 5,
|
|
2905
|
+
fallbackReservedRows: 14,
|
|
2906
|
+
minRows: 1
|
|
2907
|
+
});
|
|
2796
2908
|
useEffect11(() => {
|
|
2797
2909
|
fetchOutdated();
|
|
2798
2910
|
}, []);
|
|
@@ -2880,20 +2992,20 @@ function OutdatedView() {
|
|
|
2880
2992
|
void fetchOutdated();
|
|
2881
2993
|
}
|
|
2882
2994
|
});
|
|
2883
|
-
const
|
|
2884
|
-
const MAX_VISIBLE_ROWS = Math.max(5, terminalRows - 8);
|
|
2995
|
+
const MAX_VISIBLE_ROWS = listRows;
|
|
2885
2996
|
const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
|
|
2886
2997
|
const visible = allOutdated.slice(start, start + MAX_VISIBLE_ROWS);
|
|
2887
|
-
if (loading.outdated) return /* @__PURE__ */
|
|
2888
|
-
if (errors.outdated) return /* @__PURE__ */
|
|
2998
|
+
if (loading.outdated) return /* @__PURE__ */ jsx21(Loading, { message: t("loading_outdated") });
|
|
2999
|
+
if (errors.outdated) return /* @__PURE__ */ jsx21(ErrorMessage, { message: errors.outdated });
|
|
2889
3000
|
if (stream.isRunning || stream.lines.length > 0) {
|
|
2890
3001
|
return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
|
|
2891
|
-
/* @__PURE__ */
|
|
3002
|
+
/* @__PURE__ */ jsx21(
|
|
2892
3003
|
ProgressLog,
|
|
2893
3004
|
{
|
|
2894
3005
|
lines: stream.lines,
|
|
2895
3006
|
isRunning: stream.isRunning,
|
|
2896
|
-
title: t("outdated_upgrading")
|
|
3007
|
+
title: t("outdated_upgrading"),
|
|
3008
|
+
maxVisible: streamRows
|
|
2897
3009
|
}
|
|
2898
3010
|
),
|
|
2899
3011
|
stream.isRunning && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, children: [
|
|
@@ -2902,7 +3014,7 @@ function OutdatedView() {
|
|
|
2902
3014
|
] }),
|
|
2903
3015
|
!stream.isRunning && /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2904
3016
|
/* @__PURE__ */ jsxs18(Box17, { borderStyle: "round", borderColor: stream.error ? COLORS.error : COLORS.success, paddingX: SPACING.sm, paddingY: SPACING.none, children: [
|
|
2905
|
-
/* @__PURE__ */
|
|
3017
|
+
/* @__PURE__ */ jsx21(Text20, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("outdated_upgradeComplete")}` }),
|
|
2906
3018
|
/* @__PURE__ */ jsxs18(Text20, { color: COLORS.muted, children: [
|
|
2907
3019
|
" ",
|
|
2908
3020
|
t("outdated_pressRefresh")
|
|
@@ -2920,8 +3032,8 @@ function OutdatedView() {
|
|
|
2920
3032
|
const upgradeAllMessage = confirmAction?.type === "all" ? `${t("outdated_confirmAll", { count: allOutdated.length })}
|
|
2921
3033
|
${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ") })}` : "";
|
|
2922
3034
|
return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
|
|
2923
|
-
/* @__PURE__ */
|
|
2924
|
-
confirmAction && /* @__PURE__ */
|
|
3035
|
+
/* @__PURE__ */ jsx21(SectionHeader, { emoji: "\u{1F4E6}", title: t("outdated_title", { count: allOutdated.length }), gradient: GRADIENTS.fire }),
|
|
3036
|
+
confirmAction && /* @__PURE__ */ jsx21(Box17, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx21(
|
|
2925
3037
|
ConfirmDialog,
|
|
2926
3038
|
{
|
|
2927
3039
|
message: confirmAction.type === "all" ? upgradeAllMessage : t("outdated_confirmSingle", { name: confirmAction.type === "single" ? confirmAction.name : "" }),
|
|
@@ -2939,7 +3051,7 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
2939
3051
|
onCancel: () => setConfirmAction(null)
|
|
2940
3052
|
}
|
|
2941
3053
|
) }),
|
|
2942
|
-
allOutdated.length === 0 && !confirmAction && /* @__PURE__ */
|
|
3054
|
+
allOutdated.length === 0 && !confirmAction && /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(ResultBanner, { status: "success", message: `\u2714 ${t("outdated_upToDate")}` }) }),
|
|
2943
3055
|
allOutdated.length > 0 && !confirmAction && /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
2944
3056
|
start > 0 && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2945
3057
|
" ",
|
|
@@ -2949,31 +3061,31 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
2949
3061
|
const idx = start + i;
|
|
2950
3062
|
const isCurrent = idx === cursor;
|
|
2951
3063
|
return /* @__PURE__ */ jsxs18(SelectableRow, { isCurrent, children: [
|
|
2952
|
-
/* @__PURE__ */
|
|
2953
|
-
/* @__PURE__ */
|
|
2954
|
-
pkg.pinned && /* @__PURE__ */
|
|
3064
|
+
/* @__PURE__ */ jsx21(Text20, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.name }),
|
|
3065
|
+
/* @__PURE__ */ jsx21(VersionArrow, { current: pkg.installed_versions[0] ?? "", latest: pkg.current_version }),
|
|
3066
|
+
pkg.pinned && /* @__PURE__ */ jsx21(StatusBadge, { label: t("outdated_pinned"), variant: "info" })
|
|
2955
3067
|
] }, pkg.name);
|
|
2956
3068
|
}),
|
|
2957
3069
|
start + MAX_VISIBLE_ROWS < allOutdated.length && /* @__PURE__ */ jsxs18(Text20, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
2958
3070
|
" ",
|
|
2959
3071
|
t("scroll_moreBelow", { count: allOutdated.length - start - MAX_VISIBLE_ROWS })
|
|
2960
3072
|
] }),
|
|
2961
|
-
/* @__PURE__ */
|
|
3073
|
+
/* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.text, bold: true, children: [
|
|
2962
3074
|
cursor + 1,
|
|
2963
3075
|
"/",
|
|
2964
3076
|
allOutdated.length
|
|
2965
3077
|
] }) }),
|
|
2966
|
-
impact && !stream.isRunning && !confirmAction && /* @__PURE__ */
|
|
2967
|
-
impactLoading && !stream.isRunning && !confirmAction && /* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
3078
|
+
impact && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx21(ImpactPanel, { impact }),
|
|
3079
|
+
impactLoading && !stream.isRunning && !confirmAction && /* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: t("impact_analyzing") }) }),
|
|
3080
|
+
/* @__PURE__ */ jsx21(Box17, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx21(Text20, { color: COLORS.textSecondary, children: t("impact_hint") }) })
|
|
2969
3081
|
] })
|
|
2970
3082
|
] });
|
|
2971
3083
|
}
|
|
2972
3084
|
|
|
2973
3085
|
// src/views/package-info.tsx
|
|
2974
|
-
import { useEffect as useEffect12, useRef as
|
|
3086
|
+
import { useEffect as useEffect12, useRef as useRef6, useState as useState9 } from "react";
|
|
2975
3087
|
import { Box as Box18, Text as Text21 } from "ink";
|
|
2976
|
-
import { Fragment as Fragment4, jsx as
|
|
3088
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2977
3089
|
var ACTION_PROGRESS_KEYS = {
|
|
2978
3090
|
install: "pkgInfo_installing",
|
|
2979
3091
|
uninstall: "pkgInfo_uninstalling",
|
|
@@ -2991,9 +3103,9 @@ function PackageInfoView() {
|
|
|
2991
3103
|
const [loading, setLoading2] = useState9(true);
|
|
2992
3104
|
const [error, setError2] = useState9(null);
|
|
2993
3105
|
const [confirmAction, setConfirmAction] = useState9(null);
|
|
2994
|
-
const activeActionRef =
|
|
2995
|
-
const mountedRef =
|
|
2996
|
-
const hasRefreshed =
|
|
3106
|
+
const activeActionRef = useRef6("install");
|
|
3107
|
+
const mountedRef = useRef6(true);
|
|
3108
|
+
const hasRefreshed = useRef6(false);
|
|
2997
3109
|
const stream = useBrewStream();
|
|
2998
3110
|
useEffect12(() => {
|
|
2999
3111
|
mountedRef.current = true;
|
|
@@ -3069,20 +3181,20 @@ function PackageInfoView() {
|
|
|
3069
3181
|
}
|
|
3070
3182
|
});
|
|
3071
3183
|
if (!packageName) {
|
|
3072
|
-
return /* @__PURE__ */
|
|
3184
|
+
return /* @__PURE__ */ jsx22(Text21, { color: COLORS.textSecondary, italic: true, children: t("pkgInfo_noPackage") });
|
|
3073
3185
|
}
|
|
3074
|
-
if (loading) return /* @__PURE__ */
|
|
3075
|
-
if (error) return /* @__PURE__ */
|
|
3076
|
-
if (!formula) return /* @__PURE__ */
|
|
3186
|
+
if (loading) return /* @__PURE__ */ jsx22(Loading, { message: t("loading_package", { name: packageName }) });
|
|
3187
|
+
if (error) return /* @__PURE__ */ jsx22(ErrorMessage, { message: error });
|
|
3188
|
+
if (!formula) return /* @__PURE__ */ jsx22(ErrorMessage, { message: t("pkgInfo_notFound") });
|
|
3077
3189
|
if (stream.isRunning || stream.lines.length > 0) {
|
|
3078
3190
|
return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3079
|
-
/* @__PURE__ */
|
|
3191
|
+
/* @__PURE__ */ jsx22(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t(ACTION_PROGRESS_KEYS[activeActionRef.current] ?? ACTION_PROGRESS_KEYS["install"], { name: formula.name }) }),
|
|
3080
3192
|
stream.isRunning && /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
|
|
3081
3193
|
"esc:",
|
|
3082
3194
|
t("hint_cancel")
|
|
3083
3195
|
] }),
|
|
3084
3196
|
!stream.isRunning && /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
3085
|
-
/* @__PURE__ */
|
|
3197
|
+
/* @__PURE__ */ jsx22(Text21, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("pkgInfo_done")}` }),
|
|
3086
3198
|
/* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
|
|
3087
3199
|
"esc:",
|
|
3088
3200
|
t("hint_back")
|
|
@@ -3093,7 +3205,7 @@ function PackageInfoView() {
|
|
|
3093
3205
|
const installed = formula.installed[0];
|
|
3094
3206
|
const isInstalled = formula.installed.length > 0;
|
|
3095
3207
|
return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3096
|
-
confirmAction && /* @__PURE__ */
|
|
3208
|
+
confirmAction && /* @__PURE__ */ jsx22(
|
|
3097
3209
|
ConfirmDialog,
|
|
3098
3210
|
{
|
|
3099
3211
|
message: t(ACTION_CONFIRM_KEYS[confirmAction], { name: formula.name }),
|
|
@@ -3110,42 +3222,42 @@ function PackageInfoView() {
|
|
|
3110
3222
|
}
|
|
3111
3223
|
),
|
|
3112
3224
|
/* @__PURE__ */ jsxs19(Box18, { gap: SPACING.sm, marginBottom: SPACING.xs, children: [
|
|
3113
|
-
/* @__PURE__ */
|
|
3114
|
-
/* @__PURE__ */
|
|
3115
|
-
isInstalled && /* @__PURE__ */
|
|
3116
|
-
formula.outdated && /* @__PURE__ */
|
|
3117
|
-
formula.pinned && /* @__PURE__ */
|
|
3118
|
-
formula.keg_only && /* @__PURE__ */
|
|
3119
|
-
formula.deprecated && /* @__PURE__ */
|
|
3225
|
+
/* @__PURE__ */ jsx22(GradientText, { colors: GRADIENTS.gold, bold: true, children: formula.name }),
|
|
3226
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.teal, children: installed?.version ?? formula.versions.stable }),
|
|
3227
|
+
isInstalled && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_installed"), variant: "success" }),
|
|
3228
|
+
formula.outdated && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_outdated"), variant: "warning" }),
|
|
3229
|
+
formula.pinned && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_pinned"), variant: "info" }),
|
|
3230
|
+
formula.keg_only && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_kegOnly"), variant: "muted" }),
|
|
3231
|
+
formula.deprecated && /* @__PURE__ */ jsx22(StatusBadge, { label: t("badge_deprecated"), variant: "error" })
|
|
3120
3232
|
] }),
|
|
3121
3233
|
/* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", gap: SPACING.xs, children: [
|
|
3122
|
-
/* @__PURE__ */
|
|
3234
|
+
/* @__PURE__ */ jsx22(Text21, { children: formula.desc }),
|
|
3123
3235
|
/* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3124
|
-
/* @__PURE__ */
|
|
3236
|
+
/* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u{1F4CB}", title: t("pkgInfo_details"), gradient: [COLORS.text, COLORS.muted] }),
|
|
3125
3237
|
/* @__PURE__ */ jsxs19(Box18, { borderStyle: "round", borderColor: COLORS.border, paddingX: SPACING.sm, flexDirection: "column", children: [
|
|
3126
3238
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3127
|
-
/* @__PURE__ */
|
|
3239
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_homepage") }),
|
|
3128
3240
|
" ",
|
|
3129
3241
|
formula.homepage
|
|
3130
3242
|
] }),
|
|
3131
3243
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3132
|
-
/* @__PURE__ */
|
|
3244
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_license") }),
|
|
3133
3245
|
" ",
|
|
3134
3246
|
formula.license
|
|
3135
3247
|
] }),
|
|
3136
3248
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3137
|
-
/* @__PURE__ */
|
|
3249
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_tap") }),
|
|
3138
3250
|
" ",
|
|
3139
3251
|
formula.tap
|
|
3140
3252
|
] }),
|
|
3141
3253
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3142
|
-
/* @__PURE__ */
|
|
3254
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_stable") }),
|
|
3143
3255
|
" ",
|
|
3144
3256
|
formula.versions.stable
|
|
3145
3257
|
] }),
|
|
3146
3258
|
installed && /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
3147
3259
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3148
|
-
/* @__PURE__ */
|
|
3260
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_installed") }),
|
|
3149
3261
|
" ",
|
|
3150
3262
|
installed.version,
|
|
3151
3263
|
" (",
|
|
@@ -3153,12 +3265,12 @@ function PackageInfoView() {
|
|
|
3153
3265
|
")"
|
|
3154
3266
|
] }),
|
|
3155
3267
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3156
|
-
/* @__PURE__ */
|
|
3268
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_bottle") }),
|
|
3157
3269
|
" ",
|
|
3158
3270
|
installed.poured_from_bottle ? t("common_yes") : t("common_no")
|
|
3159
3271
|
] }),
|
|
3160
3272
|
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
3161
|
-
/* @__PURE__ */
|
|
3273
|
+
/* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: t("pkgInfo_onRequest") }),
|
|
3162
3274
|
" ",
|
|
3163
3275
|
installed.installed_on_request ? t("common_yes") : t("pkgInfo_noDependency")
|
|
3164
3276
|
] })
|
|
@@ -3166,15 +3278,18 @@ function PackageInfoView() {
|
|
|
3166
3278
|
] })
|
|
3167
3279
|
] }),
|
|
3168
3280
|
formula.dependencies.length > 0 && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3169
|
-
/* @__PURE__ */
|
|
3170
|
-
/* @__PURE__ */
|
|
3281
|
+
/* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u{1F517}", title: t("pkgInfo_dependencies", { count: formula.dependencies.length }), gradient: GRADIENTS.ocean }),
|
|
3282
|
+
/* @__PURE__ */ jsxs19(Box18, { paddingLeft: SPACING.sm, flexWrap: "wrap", columnGap: 2, children: [
|
|
3283
|
+
formula.dependencies.slice(0, 30).map((dep) => /* @__PURE__ */ jsx22(Text21, { color: COLORS.muted, children: dep }, dep)),
|
|
3284
|
+
formula.dependencies.length > 30 && /* @__PURE__ */ jsx22(Text21, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: formula.dependencies.length - 30 }) })
|
|
3285
|
+
] })
|
|
3171
3286
|
] }),
|
|
3172
3287
|
formula.caveats && /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
3173
|
-
/* @__PURE__ */
|
|
3174
|
-
/* @__PURE__ */
|
|
3288
|
+
/* @__PURE__ */ jsx22(SectionHeader, { emoji: "\u26A0\uFE0F", title: t("pkgInfo_caveats"), color: COLORS.warning }),
|
|
3289
|
+
/* @__PURE__ */ jsx22(Box18, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, children: /* @__PURE__ */ jsx22(Text21, { color: COLORS.warning, wrap: "wrap", children: formula.caveats }) })
|
|
3175
3290
|
] })
|
|
3176
3291
|
] }),
|
|
3177
|
-
/* @__PURE__ */
|
|
3292
|
+
/* @__PURE__ */ jsx22(Box18, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.textSecondary, children: [
|
|
3178
3293
|
isInstalled ? `u:${t("hint_uninstall")}` : `i:${t("hint_install")}`,
|
|
3179
3294
|
isInstalled && formula.outdated ? ` U:${t("hint_upgrade")}` : "",
|
|
3180
3295
|
` esc:${t("hint_back")}`
|
|
@@ -3183,9 +3298,9 @@ function PackageInfoView() {
|
|
|
3183
3298
|
}
|
|
3184
3299
|
|
|
3185
3300
|
// src/views/services.tsx
|
|
3186
|
-
import { useEffect as useEffect13, useState as useState10 } from "react";
|
|
3187
|
-
import { Box as Box19, Text as Text22
|
|
3188
|
-
import { jsx as
|
|
3301
|
+
import { useEffect as useEffect13, useRef as useRef7, useState as useState10 } from "react";
|
|
3302
|
+
import { Box as Box19, Text as Text22 } from "ink";
|
|
3303
|
+
import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3189
3304
|
var STATUS_VARIANTS = {
|
|
3190
3305
|
started: "success",
|
|
3191
3306
|
stopped: "muted",
|
|
@@ -3204,11 +3319,16 @@ function ServicesView() {
|
|
|
3204
3319
|
const [actionInProgress, setActionInProgress] = useState10(false);
|
|
3205
3320
|
const [confirmAction, setConfirmAction] = useState10(null);
|
|
3206
3321
|
const [lastError, setLastError] = useState10(null);
|
|
3207
|
-
const
|
|
3208
|
-
const
|
|
3209
|
-
const
|
|
3210
|
-
const
|
|
3211
|
-
const
|
|
3322
|
+
const containerRef = useRef7(null);
|
|
3323
|
+
const { width: containerWidth } = useContainerSize(containerRef);
|
|
3324
|
+
const cols = containerWidth > 0 ? containerWidth : 80;
|
|
3325
|
+
const svcNameWidth = Math.max(12, Math.floor(cols * 0.35));
|
|
3326
|
+
const svcStatusWidth = Math.max(8, Math.floor(cols * 0.15));
|
|
3327
|
+
const MAX_VISIBLE_ROWS = useVisibleRows({
|
|
3328
|
+
reservedRows: lastError || actionInProgress ? 8 : 6,
|
|
3329
|
+
fallbackReservedRows: lastError || actionInProgress ? 16 : 14,
|
|
3330
|
+
minRows: 1
|
|
3331
|
+
});
|
|
3212
3332
|
useEffect13(() => {
|
|
3213
3333
|
fetchServices();
|
|
3214
3334
|
}, []);
|
|
@@ -3241,19 +3361,19 @@ function ServicesView() {
|
|
|
3241
3361
|
else if (input === "x" || input === "2") setConfirmAction({ type: "stop", name: svc.name });
|
|
3242
3362
|
else if (input === "R" || input === "3") setConfirmAction({ type: "restart", name: svc.name });
|
|
3243
3363
|
});
|
|
3244
|
-
if (loading.services) return /* @__PURE__ */
|
|
3245
|
-
if (errors.services) return /* @__PURE__ */
|
|
3364
|
+
if (loading.services) return /* @__PURE__ */ jsx23(Loading, { message: t("loading_services") });
|
|
3365
|
+
if (errors.services) return /* @__PURE__ */ jsx23(ErrorMessage, { message: errors.services });
|
|
3246
3366
|
if (services.length === 0) {
|
|
3247
3367
|
return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", children: [
|
|
3248
|
-
/* @__PURE__ */
|
|
3249
|
-
/* @__PURE__ */
|
|
3368
|
+
/* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_title"), gradient: GRADIENTS.ocean }),
|
|
3369
|
+
/* @__PURE__ */ jsx23(Text22, { color: COLORS.textSecondary, italic: true, children: t("services_noServices") })
|
|
3250
3370
|
] });
|
|
3251
3371
|
}
|
|
3252
3372
|
const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
|
|
3253
3373
|
const visible = services.slice(start, start + MAX_VISIBLE_ROWS);
|
|
3254
|
-
return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", children: [
|
|
3255
|
-
/* @__PURE__ */
|
|
3256
|
-
confirmAction && /* @__PURE__ */
|
|
3374
|
+
return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", ref: containerRef, children: [
|
|
3375
|
+
/* @__PURE__ */ jsx23(SectionHeader, { emoji: "\u2699\uFE0F", title: t("services_titleCount", { count: services.length }), gradient: GRADIENTS.ocean }),
|
|
3376
|
+
confirmAction && /* @__PURE__ */ jsx23(Box19, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx23(
|
|
3257
3377
|
ConfirmDialog,
|
|
3258
3378
|
{
|
|
3259
3379
|
message: confirmAction.type === "stop" ? t("services_confirmStop", { name: confirmAction.name }) : t("services_confirmRestart", { name: confirmAction.name }),
|
|
@@ -3278,8 +3398,8 @@ function ServicesView() {
|
|
|
3278
3398
|
" ",
|
|
3279
3399
|
t("services_name").padEnd(svcNameWidth)
|
|
3280
3400
|
] }),
|
|
3281
|
-
/* @__PURE__ */
|
|
3282
|
-
/* @__PURE__ */
|
|
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") })
|
|
3283
3403
|
] }),
|
|
3284
3404
|
start > 0 && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3285
3405
|
" ",
|
|
@@ -3289,10 +3409,10 @@ function ServicesView() {
|
|
|
3289
3409
|
const idx = start + i;
|
|
3290
3410
|
const isCurrent = idx === cursor;
|
|
3291
3411
|
return /* @__PURE__ */ jsxs20(SelectableRow, { isCurrent, children: [
|
|
3292
|
-
/* @__PURE__ */
|
|
3293
|
-
/* @__PURE__ */
|
|
3294
|
-
/* @__PURE__ */
|
|
3295
|
-
svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */
|
|
3412
|
+
/* @__PURE__ */ jsx23(Text22, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: truncate(svc.name, svcNameWidth - 2).padEnd(svcNameWidth - 2) }),
|
|
3413
|
+
/* @__PURE__ */ jsx23(StatusBadge, { label: svc.status, variant: STATUS_VARIANTS[svc.status] }),
|
|
3414
|
+
/* @__PURE__ */ jsx23(Text22, { color: COLORS.muted, children: svc.user ?? "-" }),
|
|
3415
|
+
svc.exit_code != null && svc.exit_code !== 0 && /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: t("common_exit", { code: svc.exit_code }) })
|
|
3296
3416
|
] }, svc.name);
|
|
3297
3417
|
}),
|
|
3298
3418
|
start + MAX_VISIBLE_ROWS < services.length && /* @__PURE__ */ jsxs20(Text22, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
@@ -3300,9 +3420,9 @@ function ServicesView() {
|
|
|
3300
3420
|
t("scroll_moreBelow", { count: services.length - start - MAX_VISIBLE_ROWS })
|
|
3301
3421
|
] })
|
|
3302
3422
|
] }),
|
|
3303
|
-
actionInProgress && /* @__PURE__ */
|
|
3304
|
-
lastError && /* @__PURE__ */
|
|
3305
|
-
/* @__PURE__ */
|
|
3423
|
+
actionInProgress && /* @__PURE__ */ jsx23(Text22, { color: COLORS.sky, children: t("services_processing") }),
|
|
3424
|
+
lastError && /* @__PURE__ */ jsx23(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx23(Text22, { color: COLORS.error, children: lastError }) }),
|
|
3425
|
+
/* @__PURE__ */ jsx23(Box19, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs20(Text22, { color: COLORS.text, bold: true, children: [
|
|
3306
3426
|
cursor + 1,
|
|
3307
3427
|
"/",
|
|
3308
3428
|
services.length
|
|
@@ -3311,12 +3431,18 @@ function ServicesView() {
|
|
|
3311
3431
|
}
|
|
3312
3432
|
|
|
3313
3433
|
// src/views/doctor.tsx
|
|
3314
|
-
import { useEffect as useEffect14, useRef as
|
|
3434
|
+
import { useEffect as useEffect14, useRef as useRef8, useState as useState11 } from "react";
|
|
3315
3435
|
import { Box as Box20, Text as Text23 } from "ink";
|
|
3316
|
-
import { jsx as
|
|
3436
|
+
import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3317
3437
|
function DoctorView() {
|
|
3318
3438
|
const { doctorWarnings, doctorClean, loading, errors, fetchDoctor } = useBrewStore();
|
|
3319
|
-
const
|
|
3439
|
+
const [cursor, setCursor] = useState11(0);
|
|
3440
|
+
const visibleWarnings = useVisibleRows({
|
|
3441
|
+
reservedRows: 6,
|
|
3442
|
+
fallbackReservedRows: 14,
|
|
3443
|
+
minRows: 1
|
|
3444
|
+
});
|
|
3445
|
+
const mountedRef = useRef8(true);
|
|
3320
3446
|
useEffect14(() => {
|
|
3321
3447
|
mountedRef.current = true;
|
|
3322
3448
|
return () => {
|
|
@@ -3326,27 +3452,42 @@ function DoctorView() {
|
|
|
3326
3452
|
useEffect14(() => {
|
|
3327
3453
|
fetchDoctor();
|
|
3328
3454
|
}, []);
|
|
3329
|
-
useViewInput((input) => {
|
|
3330
|
-
if (input === "r" || input === "1")
|
|
3455
|
+
useViewInput((input, key) => {
|
|
3456
|
+
if (input === "r" || input === "1") {
|
|
3457
|
+
void fetchDoctor();
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, doctorWarnings.length - 1)));
|
|
3461
|
+
else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
|
|
3331
3462
|
});
|
|
3332
|
-
if (loading.doctor) return /* @__PURE__ */
|
|
3333
|
-
if (errors.doctor) return /* @__PURE__ */
|
|
3463
|
+
if (loading.doctor) return /* @__PURE__ */ jsx24(Loading, { message: t("loading_doctor") });
|
|
3464
|
+
if (errors.doctor) return /* @__PURE__ */ jsx24(ErrorMessage, { message: errors.doctor });
|
|
3465
|
+
const start = Math.max(0, cursor - Math.floor(visibleWarnings / 2));
|
|
3466
|
+
const visible = doctorWarnings.slice(start, start + visibleWarnings);
|
|
3334
3467
|
return /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", children: [
|
|
3335
|
-
/* @__PURE__ */
|
|
3468
|
+
/* @__PURE__ */ jsx24(SectionHeader, { emoji: "\u{1FA7A}", title: t("doctor_title"), gradient: GRADIENTS.emerald }),
|
|
3336
3469
|
/* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
3337
|
-
doctorClean && /* @__PURE__ */
|
|
3338
|
-
doctorClean === false && doctorWarnings.length === 0 && /* @__PURE__ */
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
)
|
|
3470
|
+
doctorClean && /* @__PURE__ */ jsx24(ResultBanner, { status: "success", message: `\u2714 ${t("doctor_clean")}` }),
|
|
3471
|
+
doctorClean === false && doctorWarnings.length === 0 && /* @__PURE__ */ jsx24(Text23, { color: COLORS.warning, children: t("doctor_warningsNotCaptured") }),
|
|
3472
|
+
start > 0 && /* @__PURE__ */ jsxs21(Text23, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3473
|
+
" ",
|
|
3474
|
+
t("scroll_moreAbove", { count: start })
|
|
3475
|
+
] }),
|
|
3476
|
+
visible.map((warning, i) => {
|
|
3477
|
+
const idx = start + i;
|
|
3478
|
+
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)}`);
|
|
3479
|
+
}),
|
|
3480
|
+
start + visibleWarnings < doctorWarnings.length && /* @__PURE__ */ jsxs21(Text23, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
3481
|
+
" ",
|
|
3482
|
+
t("scroll_moreBelow", { count: doctorWarnings.length - start - visibleWarnings })
|
|
3483
|
+
] })
|
|
3343
3484
|
] }),
|
|
3344
|
-
/* @__PURE__ */
|
|
3485
|
+
/* @__PURE__ */ jsx24(Box20, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx24(Text23, { color: COLORS.text, bold: true, children: doctorWarnings.length > 0 ? tp("plural_warnings", doctorWarnings.length) : "" }) })
|
|
3345
3486
|
] });
|
|
3346
3487
|
}
|
|
3347
3488
|
|
|
3348
3489
|
// src/views/profiles.tsx
|
|
3349
|
-
import { useEffect as useEffect15, useRef as
|
|
3490
|
+
import { useEffect as useEffect15, useRef as useRef9, useState as useState12 } from "react";
|
|
3350
3491
|
import { Box as Box25 } from "ink";
|
|
3351
3492
|
|
|
3352
3493
|
// src/stores/profile-store.ts
|
|
@@ -3568,12 +3709,12 @@ var useProfileStore = create9((set) => ({
|
|
|
3568
3709
|
|
|
3569
3710
|
// src/views/profiles/profile-list-mode.tsx
|
|
3570
3711
|
import { Box as Box21, Text as Text24 } from "ink";
|
|
3571
|
-
import { jsx as
|
|
3712
|
+
import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3572
3713
|
function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onConfirmDelete, onCancelDelete }) {
|
|
3573
3714
|
return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
|
|
3574
|
-
/* @__PURE__ */
|
|
3575
|
-
loadError && /* @__PURE__ */
|
|
3576
|
-
confirmDelete && profileNames[cursor] && /* @__PURE__ */
|
|
3715
|
+
/* @__PURE__ */ jsx25(SectionHeader, { emoji: "\u{1F4C1}", title: t("profiles_title", { count: profileNames.length }), gradient: GRADIENTS.gold }),
|
|
3716
|
+
loadError && /* @__PURE__ */ jsx25(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx25(Text24, { color: COLORS.error, children: loadError }) }),
|
|
3717
|
+
confirmDelete && profileNames[cursor] && /* @__PURE__ */ jsx25(Box21, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx25(
|
|
3577
3718
|
ConfirmDialog,
|
|
3578
3719
|
{
|
|
3579
3720
|
message: t("profiles_confirmDelete", { name: profileNames[cursor] }),
|
|
@@ -3581,12 +3722,12 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
|
|
|
3581
3722
|
onCancel: onCancelDelete
|
|
3582
3723
|
}
|
|
3583
3724
|
) }),
|
|
3584
|
-
profileNames.length === 0 && !confirmDelete && /* @__PURE__ */
|
|
3585
|
-
/* @__PURE__ */
|
|
3725
|
+
profileNames.length === 0 && !confirmDelete && /* @__PURE__ */ jsx25(Box21, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.textSecondary, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
|
|
3726
|
+
/* @__PURE__ */ jsx25(Text24, { color: COLORS.textSecondary, italic: true, children: t("profiles_noProfiles") }),
|
|
3586
3727
|
/* @__PURE__ */ jsxs22(Text24, { color: COLORS.muted, children: [
|
|
3587
3728
|
t("profiles_press"),
|
|
3588
3729
|
" ",
|
|
3589
|
-
/* @__PURE__ */
|
|
3730
|
+
/* @__PURE__ */ jsx25(Text24, { color: COLORS.gold, bold: true, children: "n" }),
|
|
3590
3731
|
" ",
|
|
3591
3732
|
t("profiles_exportHint")
|
|
3592
3733
|
] })
|
|
@@ -3594,9 +3735,9 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
|
|
|
3594
3735
|
profileNames.length > 0 && !confirmDelete && /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
3595
3736
|
profileNames.map((name, i) => {
|
|
3596
3737
|
const isCurrent = i === cursor;
|
|
3597
|
-
return /* @__PURE__ */
|
|
3738
|
+
return /* @__PURE__ */ jsx25(SelectableRow, { isCurrent, children: /* @__PURE__ */ jsx25(Text24, { bold: isCurrent, inverse: isCurrent, children: name }) }, name);
|
|
3598
3739
|
}),
|
|
3599
|
-
/* @__PURE__ */
|
|
3740
|
+
/* @__PURE__ */ jsx25(Box21, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs22(Text24, { color: COLORS.text, bold: true, children: [
|
|
3600
3741
|
cursor + 1,
|
|
3601
3742
|
"/",
|
|
3602
3743
|
profileNames.length
|
|
@@ -3607,22 +3748,37 @@ function ProfileListMode({ profileNames, cursor, confirmDelete, loadError, onCon
|
|
|
3607
3748
|
|
|
3608
3749
|
// src/views/profiles/profile-detail-mode.tsx
|
|
3609
3750
|
import { Box as Box22, Text as Text25 } from "ink";
|
|
3610
|
-
import { jsx as
|
|
3751
|
+
import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3611
3752
|
function ProfileDetailMode({ profile }) {
|
|
3753
|
+
const totalRows = useVisibleRows({
|
|
3754
|
+
reservedRows: 7,
|
|
3755
|
+
fallbackReservedRows: 14,
|
|
3756
|
+
minRows: 2
|
|
3757
|
+
});
|
|
3758
|
+
const total = profile.formulae.length + profile.casks.length;
|
|
3759
|
+
const formulaeBudget = total === 0 ? 0 : Math.min(profile.formulae.length, Math.max(1, Math.round(profile.formulae.length / total * totalRows)));
|
|
3760
|
+
const casksBudget = Math.max(0, totalRows - formulaeBudget);
|
|
3761
|
+
const visibleFormulae = profile.formulae.slice(0, formulaeBudget);
|
|
3762
|
+
const visibleCasks = profile.casks.slice(0, casksBudget);
|
|
3763
|
+
const formulaeHidden = profile.formulae.length - visibleFormulae.length;
|
|
3764
|
+
const casksHidden = profile.casks.length - visibleCasks.length;
|
|
3612
3765
|
return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
|
|
3613
|
-
/* @__PURE__ */
|
|
3614
|
-
/* @__PURE__ */
|
|
3615
|
-
/* @__PURE__ */
|
|
3766
|
+
/* @__PURE__ */ jsx26(Text25, { bold: true, color: COLORS.gold, children: profile.name }),
|
|
3767
|
+
/* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, wrap: "wrap", children: profile.description }),
|
|
3768
|
+
/* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: t("profiles_created", { date: formatDate(profile.createdAt) }) }),
|
|
3616
3769
|
/* @__PURE__ */ jsxs23(Box22, { marginTop: SPACING.xs, flexDirection: "column", children: [
|
|
3617
|
-
/* @__PURE__ */
|
|
3770
|
+
/* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_formulaeCount", { count: profile.formulae.length }) }),
|
|
3618
3771
|
/* @__PURE__ */ jsxs23(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
3619
|
-
|
|
3620
|
-
|
|
3772
|
+
visibleFormulae.map((f) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: f }, f)),
|
|
3773
|
+
formulaeHidden > 0 && /* @__PURE__ */ jsx26(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: formulaeHidden }) })
|
|
3621
3774
|
] }),
|
|
3622
|
-
/* @__PURE__ */
|
|
3623
|
-
/* @__PURE__ */
|
|
3775
|
+
/* @__PURE__ */ jsx26(Text25, { bold: true, children: t("profiles_casksCount", { count: profile.casks.length }) }),
|
|
3776
|
+
/* @__PURE__ */ jsxs23(Box22, { paddingLeft: SPACING.sm, flexDirection: "column", children: [
|
|
3777
|
+
visibleCasks.map((c) => /* @__PURE__ */ jsx26(Text25, { color: COLORS.muted, children: c }, c)),
|
|
3778
|
+
casksHidden > 0 && /* @__PURE__ */ jsx26(Text25, { color: COLORS.textSecondary, italic: true, children: t("common_andMore", { count: casksHidden }) })
|
|
3779
|
+
] })
|
|
3624
3780
|
] }),
|
|
3625
|
-
/* @__PURE__ */
|
|
3781
|
+
/* @__PURE__ */ jsx26(Box22, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs23(Text25, { color: COLORS.textSecondary, children: [
|
|
3626
3782
|
"esc:",
|
|
3627
3783
|
t("hint_back"),
|
|
3628
3784
|
" e:",
|
|
@@ -3636,11 +3792,11 @@ function ProfileDetailMode({ profile }) {
|
|
|
3636
3792
|
// src/views/profiles/profile-create-flow.tsx
|
|
3637
3793
|
import { Box as Box23, Text as Text26 } from "ink";
|
|
3638
3794
|
import { TextInput as TextInput3 } from "@inkjs/ui";
|
|
3639
|
-
import { jsx as
|
|
3795
|
+
import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3640
3796
|
function ProfileCreateName({ onSubmit }) {
|
|
3641
3797
|
return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", children: [
|
|
3642
|
-
/* @__PURE__ */
|
|
3643
|
-
/* @__PURE__ */
|
|
3798
|
+
/* @__PURE__ */ jsx27(Text26, { bold: true, children: t("profiles_createName") }),
|
|
3799
|
+
/* @__PURE__ */ jsx27(
|
|
3644
3800
|
TextInput3,
|
|
3645
3801
|
{
|
|
3646
3802
|
placeholder: t("profiles_namePlaceholder"),
|
|
@@ -3651,12 +3807,12 @@ function ProfileCreateName({ onSubmit }) {
|
|
|
3651
3807
|
}
|
|
3652
3808
|
function ProfileCreateDesc({ name, loadError, onSubmit }) {
|
|
3653
3809
|
return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", children: [
|
|
3654
|
-
/* @__PURE__ */
|
|
3810
|
+
/* @__PURE__ */ jsx27(Text26, { bold: true, children: t("profiles_createDesc", { name }) }),
|
|
3655
3811
|
loadError && /* @__PURE__ */ jsxs24(Text26, { color: COLORS.error, children: [
|
|
3656
3812
|
t("error_prefix"),
|
|
3657
3813
|
loadError
|
|
3658
3814
|
] }),
|
|
3659
|
-
/* @__PURE__ */
|
|
3815
|
+
/* @__PURE__ */ jsx27(
|
|
3660
3816
|
TextInput3,
|
|
3661
3817
|
{
|
|
3662
3818
|
placeholder: t("profiles_descPlaceholder"),
|
|
@@ -3669,11 +3825,11 @@ function ProfileCreateDesc({ name, loadError, onSubmit }) {
|
|
|
3669
3825
|
// src/views/profiles/profile-edit-flow.tsx
|
|
3670
3826
|
import { Box as Box24, Text as Text27 } from "ink";
|
|
3671
3827
|
import { TextInput as TextInput4 } from "@inkjs/ui";
|
|
3672
|
-
import { jsx as
|
|
3828
|
+
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3673
3829
|
function ProfileEditName({ defaultName, onSubmit }) {
|
|
3674
3830
|
return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", children: [
|
|
3675
|
-
/* @__PURE__ */
|
|
3676
|
-
/* @__PURE__ */
|
|
3831
|
+
/* @__PURE__ */ jsx28(Text27, { bold: true, children: t("profiles_editName") }),
|
|
3832
|
+
/* @__PURE__ */ jsx28(
|
|
3677
3833
|
TextInput4,
|
|
3678
3834
|
{
|
|
3679
3835
|
defaultValue: defaultName,
|
|
@@ -3684,12 +3840,12 @@ function ProfileEditName({ defaultName, onSubmit }) {
|
|
|
3684
3840
|
}
|
|
3685
3841
|
function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
|
|
3686
3842
|
return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", children: [
|
|
3687
|
-
/* @__PURE__ */
|
|
3843
|
+
/* @__PURE__ */ jsx28(Text27, { bold: true, children: t("profiles_editDesc", { name }) }),
|
|
3688
3844
|
loadError && /* @__PURE__ */ jsxs25(Text27, { color: COLORS.error, children: [
|
|
3689
3845
|
t("error_prefix"),
|
|
3690
3846
|
loadError
|
|
3691
3847
|
] }),
|
|
3692
|
-
/* @__PURE__ */
|
|
3848
|
+
/* @__PURE__ */ jsx28(
|
|
3693
3849
|
TextInput4,
|
|
3694
3850
|
{
|
|
3695
3851
|
defaultValue: defaultDesc,
|
|
@@ -3700,22 +3856,22 @@ function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
|
|
|
3700
3856
|
}
|
|
3701
3857
|
|
|
3702
3858
|
// src/views/profiles.tsx
|
|
3703
|
-
import { jsx as
|
|
3859
|
+
import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3704
3860
|
function ProfilesView() {
|
|
3705
3861
|
const { profileNames, selectedProfile, loading, loadError, fetchProfiles, loadProfile: loadProfile2, exportCurrent, deleteProfile: deleteProfile2, updateProfile: updateProfile2 } = useProfileStore();
|
|
3706
|
-
const [cursor, setCursor] =
|
|
3707
|
-
const [mode, setMode] =
|
|
3708
|
-
const [newName, setNewName] =
|
|
3709
|
-
const [confirmDelete, setConfirmDelete] =
|
|
3710
|
-
const [editName, setEditName] =
|
|
3711
|
-
const [editDesc, setEditDesc] =
|
|
3712
|
-
const [importLines, setImportLines] =
|
|
3713
|
-
const [importRunning, setImportRunning] =
|
|
3714
|
-
const [importHadError, setImportHadError] =
|
|
3715
|
-
const [importProfile2, setImportProfile] =
|
|
3862
|
+
const [cursor, setCursor] = useState12(0);
|
|
3863
|
+
const [mode, setMode] = useState12("list");
|
|
3864
|
+
const [newName, setNewName] = useState12("");
|
|
3865
|
+
const [confirmDelete, setConfirmDelete] = useState12(false);
|
|
3866
|
+
const [editName, setEditName] = useState12("");
|
|
3867
|
+
const [editDesc, setEditDesc] = useState12("");
|
|
3868
|
+
const [importLines, setImportLines] = useState12([]);
|
|
3869
|
+
const [importRunning, setImportRunning] = useState12(false);
|
|
3870
|
+
const [importHadError, setImportHadError] = useState12(false);
|
|
3871
|
+
const [importProfile2, setImportProfile] = useState12(null);
|
|
3716
3872
|
const { openModal, closeModal } = useModalStore();
|
|
3717
|
-
const importGenRef =
|
|
3718
|
-
const mountedRef =
|
|
3873
|
+
const importGenRef = useRef9(null);
|
|
3874
|
+
const mountedRef = useRef9(true);
|
|
3719
3875
|
useEffect15(() => {
|
|
3720
3876
|
fetchProfiles();
|
|
3721
3877
|
}, []);
|
|
@@ -3809,9 +3965,9 @@ function ProfilesView() {
|
|
|
3809
3965
|
}
|
|
3810
3966
|
}
|
|
3811
3967
|
};
|
|
3812
|
-
if (loading) return /* @__PURE__ */
|
|
3968
|
+
if (loading) return /* @__PURE__ */ jsx29(Loading, { message: t("loading_profiles") });
|
|
3813
3969
|
if (mode === "confirm-import" && importProfile2) {
|
|
3814
|
-
return /* @__PURE__ */
|
|
3970
|
+
return /* @__PURE__ */ jsx29(Box25, { flexDirection: "column", children: /* @__PURE__ */ jsx29(
|
|
3815
3971
|
ConfirmDialog,
|
|
3816
3972
|
{
|
|
3817
3973
|
message: t("profiles_importSummary", {
|
|
@@ -3832,18 +3988,18 @@ function ProfilesView() {
|
|
|
3832
3988
|
}
|
|
3833
3989
|
if (mode === "importing") {
|
|
3834
3990
|
return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", children: [
|
|
3835
|
-
/* @__PURE__ */
|
|
3836
|
-
!importRunning && /* @__PURE__ */
|
|
3991
|
+
/* @__PURE__ */ jsx29(ProgressLog, { lines: importLines, isRunning: importRunning, title: t("profiles_importTitle") }),
|
|
3992
|
+
!importRunning && /* @__PURE__ */ jsx29(Box25, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx29(ResultBanner, { status: importHadError ? "error" : "success", message: importHadError ? t("profiles_importPartial") : `\u2714 ${t("profiles_importComplete")}` }) })
|
|
3837
3993
|
] });
|
|
3838
3994
|
}
|
|
3839
3995
|
if (mode === "create-name") {
|
|
3840
|
-
return /* @__PURE__ */
|
|
3996
|
+
return /* @__PURE__ */ jsx29(ProfileCreateName, { onSubmit: (val) => {
|
|
3841
3997
|
setNewName(val);
|
|
3842
3998
|
setMode("create-desc");
|
|
3843
3999
|
} });
|
|
3844
4000
|
}
|
|
3845
4001
|
if (mode === "create-desc") {
|
|
3846
|
-
return /* @__PURE__ */
|
|
4002
|
+
return /* @__PURE__ */ jsx29(
|
|
3847
4003
|
ProfileCreateDesc,
|
|
3848
4004
|
{
|
|
3849
4005
|
name: newName,
|
|
@@ -3860,13 +4016,13 @@ function ProfilesView() {
|
|
|
3860
4016
|
);
|
|
3861
4017
|
}
|
|
3862
4018
|
if (mode === "edit-name") {
|
|
3863
|
-
return /* @__PURE__ */
|
|
4019
|
+
return /* @__PURE__ */ jsx29(ProfileEditName, { defaultName: editName, onSubmit: (val) => {
|
|
3864
4020
|
setEditName(val);
|
|
3865
4021
|
setMode("edit-desc");
|
|
3866
4022
|
} });
|
|
3867
4023
|
}
|
|
3868
4024
|
if (mode === "edit-desc") {
|
|
3869
|
-
return /* @__PURE__ */
|
|
4025
|
+
return /* @__PURE__ */ jsx29(
|
|
3870
4026
|
ProfileEditDesc,
|
|
3871
4027
|
{
|
|
3872
4028
|
name: editName,
|
|
@@ -3884,9 +4040,9 @@ function ProfilesView() {
|
|
|
3884
4040
|
);
|
|
3885
4041
|
}
|
|
3886
4042
|
if (mode === "detail" && selectedProfile) {
|
|
3887
|
-
return /* @__PURE__ */
|
|
4043
|
+
return /* @__PURE__ */ jsx29(ProfileDetailMode, { profile: selectedProfile });
|
|
3888
4044
|
}
|
|
3889
|
-
return /* @__PURE__ */
|
|
4045
|
+
return /* @__PURE__ */ jsx29(
|
|
3890
4046
|
ProfileListMode,
|
|
3891
4047
|
{
|
|
3892
4048
|
profileNames,
|
|
@@ -3903,7 +4059,7 @@ function ProfilesView() {
|
|
|
3903
4059
|
}
|
|
3904
4060
|
|
|
3905
4061
|
// src/views/smart-cleanup.tsx
|
|
3906
|
-
import { useEffect as useEffect16, useRef as
|
|
4062
|
+
import { useEffect as useEffect16, useRef as useRef10, useState as useState13 } from "react";
|
|
3907
4063
|
import { Box as Box26, Text as Text28 } from "ink";
|
|
3908
4064
|
|
|
3909
4065
|
// src/stores/cleanup-store.ts
|
|
@@ -4024,15 +4180,20 @@ var useCleanupStore = create10((set, get) => ({
|
|
|
4024
4180
|
}));
|
|
4025
4181
|
|
|
4026
4182
|
// src/views/smart-cleanup.tsx
|
|
4027
|
-
import { jsx as
|
|
4183
|
+
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4028
4184
|
function SmartCleanupView() {
|
|
4029
4185
|
const { summary, selected, loading, error, analyze, toggleSelect, selectAll } = useCleanupStore();
|
|
4030
|
-
const [cursor, setCursor] =
|
|
4031
|
-
const [confirmClean, setConfirmClean] =
|
|
4032
|
-
const [confirmForce, setConfirmForce] =
|
|
4033
|
-
const [failedNames, setFailedNames] =
|
|
4186
|
+
const [cursor, setCursor] = useState13(0);
|
|
4187
|
+
const [confirmClean, setConfirmClean] = useState13(false);
|
|
4188
|
+
const [confirmForce, setConfirmForce] = useState13(false);
|
|
4189
|
+
const [failedNames, setFailedNames] = useState13([]);
|
|
4034
4190
|
const stream = useBrewStream();
|
|
4035
|
-
const hasRefreshed =
|
|
4191
|
+
const hasRefreshed = useRef10(false);
|
|
4192
|
+
const listRows = useVisibleRows({
|
|
4193
|
+
reservedRows: confirmClean || confirmForce ? 12 : 9,
|
|
4194
|
+
fallbackReservedRows: confirmClean || confirmForce ? 18 : 14,
|
|
4195
|
+
minRows: 1
|
|
4196
|
+
});
|
|
4036
4197
|
useEffect16(() => {
|
|
4037
4198
|
analyze();
|
|
4038
4199
|
}, []);
|
|
@@ -4075,18 +4236,18 @@ function SmartCleanupView() {
|
|
|
4075
4236
|
if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, candidates.length - 1)));
|
|
4076
4237
|
else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
|
|
4077
4238
|
});
|
|
4078
|
-
if (loading) return /* @__PURE__ */
|
|
4079
|
-
if (error) return /* @__PURE__ */
|
|
4239
|
+
if (loading) return /* @__PURE__ */ jsx30(Loading, { message: t("loading_cleanup") });
|
|
4240
|
+
if (error) return /* @__PURE__ */ jsx30(ErrorMessage, { message: error });
|
|
4080
4241
|
if (stream.isRunning || stream.lines.length > 0) {
|
|
4081
4242
|
return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
|
|
4082
|
-
/* @__PURE__ */
|
|
4243
|
+
/* @__PURE__ */ jsx30(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("cleanup_cleaning") }),
|
|
4083
4244
|
stream.isRunning && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.muted, children: [
|
|
4084
4245
|
"esc:",
|
|
4085
4246
|
t("hint_cancel")
|
|
4086
4247
|
] }),
|
|
4087
|
-
!stream.isRunning && !stream.error && /* @__PURE__ */
|
|
4248
|
+
!stream.isRunning && !stream.error && /* @__PURE__ */ jsx30(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_complete")}` }),
|
|
4088
4249
|
!stream.isRunning && stream.error && /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", gap: SPACING.xs, children: [
|
|
4089
|
-
/* @__PURE__ */
|
|
4250
|
+
/* @__PURE__ */ jsx30(ResultBanner, { status: "error", message: `\u2718 ${t("cleanup_depError")}` }),
|
|
4090
4251
|
isDependencyError && failedNames.length > 0 && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.warning, children: [
|
|
4091
4252
|
"F:",
|
|
4092
4253
|
t("hint_force"),
|
|
@@ -4094,7 +4255,7 @@ function SmartCleanupView() {
|
|
|
4094
4255
|
t("hint_refresh")
|
|
4095
4256
|
] })
|
|
4096
4257
|
] }),
|
|
4097
|
-
confirmForce && /* @__PURE__ */
|
|
4258
|
+
confirmForce && /* @__PURE__ */ jsx30(Box26, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx30(
|
|
4098
4259
|
ConfirmDialog,
|
|
4099
4260
|
{
|
|
4100
4261
|
message: t("cleanup_confirmForce", { count: failedNames.length }),
|
|
@@ -4110,15 +4271,15 @@ function SmartCleanupView() {
|
|
|
4110
4271
|
] });
|
|
4111
4272
|
}
|
|
4112
4273
|
return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
|
|
4113
|
-
/* @__PURE__ */
|
|
4274
|
+
/* @__PURE__ */ jsx30(SectionHeader, { emoji: "\u{1F9F9}", title: t("cleanup_title"), gradient: GRADIENTS.emerald }),
|
|
4114
4275
|
summary && /* @__PURE__ */ jsxs27(Box26, { gap: SPACING.xs, marginY: SPACING.xs, children: [
|
|
4115
|
-
/* @__PURE__ */
|
|
4116
|
-
/* @__PURE__ */
|
|
4117
|
-
/* @__PURE__ */
|
|
4276
|
+
/* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_orphans"), value: candidates.length, color: candidates.length > 0 ? COLORS.warning : COLORS.success }),
|
|
4277
|
+
/* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_reclaimable"), value: summary.totalReclaimableFormatted, color: COLORS.sky }),
|
|
4278
|
+
/* @__PURE__ */ jsx30(StatCard, { label: t("cleanup_selected"), value: selected.size, color: selected.size > 0 ? COLORS.success : COLORS.muted })
|
|
4118
4279
|
] }),
|
|
4119
4280
|
confirmClean && /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", marginY: SPACING.xs, gap: SPACING.xs, children: [
|
|
4120
|
-
/* @__PURE__ */
|
|
4121
|
-
/* @__PURE__ */
|
|
4281
|
+
/* @__PURE__ */ jsx30(Box26, { borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx30(Text28, { color: COLORS.warning, children: t("cleanup_warning_system_tools") }) }),
|
|
4282
|
+
/* @__PURE__ */ jsx30(
|
|
4122
4283
|
ConfirmDialog,
|
|
4123
4284
|
{
|
|
4124
4285
|
message: t("cleanup_confirmUninstall", { count: selected.size }),
|
|
@@ -4133,34 +4294,47 @@ function SmartCleanupView() {
|
|
|
4133
4294
|
}
|
|
4134
4295
|
)
|
|
4135
4296
|
] }),
|
|
4136
|
-
candidates.length === 0 && !confirmClean && /* @__PURE__ */
|
|
4137
|
-
candidates.length > 0 && !confirmClean &&
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4297
|
+
candidates.length === 0 && !confirmClean && /* @__PURE__ */ jsx30(ResultBanner, { status: "success", message: `\u2714 ${t("cleanup_systemClean")}` }),
|
|
4298
|
+
candidates.length > 0 && !confirmClean && (() => {
|
|
4299
|
+
const start = Math.max(0, cursor - Math.floor(listRows / 2));
|
|
4300
|
+
const visible = candidates.slice(start, start + listRows);
|
|
4301
|
+
return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", children: [
|
|
4302
|
+
start > 0 && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4303
|
+
" ",
|
|
4304
|
+
t("scroll_moreAbove", { count: start })
|
|
4305
|
+
] }),
|
|
4306
|
+
visible.map((c, i) => {
|
|
4307
|
+
const idx = start + i;
|
|
4308
|
+
const isCurrent = idx === cursor;
|
|
4309
|
+
const isSelected = selected.has(c.name);
|
|
4310
|
+
return /* @__PURE__ */ jsxs27(SelectableRow, { isCurrent, children: [
|
|
4311
|
+
/* @__PURE__ */ jsx30(Text28, { color: isSelected ? COLORS.success : COLORS.muted, children: isSelected ? "\u2611" : "\u2610" }),
|
|
4312
|
+
/* @__PURE__ */ jsx30(Text28, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: c.name }),
|
|
4313
|
+
/* @__PURE__ */ jsx30(Text28, { color: COLORS.warning, children: c.diskUsageFormatted }),
|
|
4314
|
+
/* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, children: [
|
|
4315
|
+
"[",
|
|
4316
|
+
c.reason,
|
|
4317
|
+
"]"
|
|
4318
|
+
] })
|
|
4319
|
+
] }, c.name);
|
|
4320
|
+
}),
|
|
4321
|
+
start + listRows < candidates.length && /* @__PURE__ */ jsxs27(Text28, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4322
|
+
" ",
|
|
4323
|
+
t("scroll_moreBelow", { count: candidates.length - start - listRows })
|
|
4324
|
+
] }),
|
|
4325
|
+
/* @__PURE__ */ jsx30(Box26, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs27(Text28, { color: COLORS.text, bold: true, children: [
|
|
4326
|
+
cursor + 1,
|
|
4327
|
+
"/",
|
|
4328
|
+
candidates.length
|
|
4329
|
+
] }) })
|
|
4330
|
+
] });
|
|
4331
|
+
})()
|
|
4158
4332
|
] });
|
|
4159
4333
|
}
|
|
4160
4334
|
|
|
4161
4335
|
// src/views/history.tsx
|
|
4162
|
-
import { useEffect as useEffect17, useState as
|
|
4163
|
-
import { Box as Box27, Text as Text29
|
|
4336
|
+
import { useEffect as useEffect17, useState as useState14, useMemo as useMemo5 } from "react";
|
|
4337
|
+
import { Box as Box27, Text as Text29 } from "ink";
|
|
4164
4338
|
|
|
4165
4339
|
// src/stores/history-store.ts
|
|
4166
4340
|
import { create as create11 } from "zustand";
|
|
@@ -4196,7 +4370,7 @@ var useHistoryStore = create11((set) => ({
|
|
|
4196
4370
|
}));
|
|
4197
4371
|
|
|
4198
4372
|
// src/views/history.tsx
|
|
4199
|
-
import { jsx as
|
|
4373
|
+
import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4200
4374
|
var ACTION_ICONS = {
|
|
4201
4375
|
install: { icon: "+", color: COLORS.success },
|
|
4202
4376
|
uninstall: { icon: "-", color: COLORS.error },
|
|
@@ -4212,17 +4386,25 @@ var ACTION_LABEL_KEYS = {
|
|
|
4212
4386
|
var FILTERS = ["all", "install", "uninstall", "upgrade", "upgrade-all"];
|
|
4213
4387
|
function HistoryView() {
|
|
4214
4388
|
const { entries, loading, error, fetchHistory, clearHistory: clearHistory2 } = useHistoryStore();
|
|
4215
|
-
const [cursor, setCursor] =
|
|
4216
|
-
const [filter, setFilter] =
|
|
4217
|
-
const [searchQuery, setSearchQuery] =
|
|
4218
|
-
const [isSearching, setIsSearching] =
|
|
4219
|
-
const [confirmClear, setConfirmClear] =
|
|
4220
|
-
const [confirmReplay, setConfirmReplay] =
|
|
4389
|
+
const [cursor, setCursor] = useState14(0);
|
|
4390
|
+
const [filter, setFilter] = useState14("all");
|
|
4391
|
+
const [searchQuery, setSearchQuery] = useState14("");
|
|
4392
|
+
const [isSearching, setIsSearching] = useState14(false);
|
|
4393
|
+
const [confirmClear, setConfirmClear] = useState14(false);
|
|
4394
|
+
const [confirmReplay, setConfirmReplay] = useState14(null);
|
|
4221
4395
|
const stream = useBrewStream();
|
|
4222
4396
|
const debouncedQuery = useDebounce(searchQuery, 200);
|
|
4223
4397
|
const { openModal, closeModal } = useModalStore();
|
|
4224
|
-
const
|
|
4225
|
-
|
|
4398
|
+
const MAX_VISIBLE_ROWS = useVisibleRows({
|
|
4399
|
+
reservedRows: isSearching || stream.lines.length > 0 || stream.isRunning ? 8 : 5,
|
|
4400
|
+
fallbackReservedRows: isSearching || stream.lines.length > 0 || stream.isRunning ? 16 : 13,
|
|
4401
|
+
minRows: 1
|
|
4402
|
+
});
|
|
4403
|
+
const streamRows = useVisibleRows({
|
|
4404
|
+
reservedRows: 7,
|
|
4405
|
+
fallbackReservedRows: 16,
|
|
4406
|
+
minRows: 1
|
|
4407
|
+
});
|
|
4226
4408
|
useEffect17(() => {
|
|
4227
4409
|
fetchHistory();
|
|
4228
4410
|
}, []);
|
|
@@ -4276,17 +4458,17 @@ function HistoryView() {
|
|
|
4276
4458
|
if (input === "j" || key.downArrow) setCursor((c) => Math.min(c + 1, Math.max(0, filtered.length - 1)));
|
|
4277
4459
|
else if (input === "k" || key.upArrow) setCursor((c) => Math.max(c - 1, 0));
|
|
4278
4460
|
});
|
|
4279
|
-
if (loading) return /* @__PURE__ */
|
|
4280
|
-
if (error) return /* @__PURE__ */
|
|
4461
|
+
if (loading) return /* @__PURE__ */ jsx31(Loading, { message: t("loading_history") });
|
|
4462
|
+
if (error) return /* @__PURE__ */ jsx31(ErrorMessage, { message: error });
|
|
4281
4463
|
const start = Math.max(0, cursor - Math.floor(MAX_VISIBLE_ROWS / 2));
|
|
4282
4464
|
const visible = filtered.slice(start, start + MAX_VISIBLE_ROWS);
|
|
4283
4465
|
return /* @__PURE__ */ jsxs28(Box27, { flexDirection: "column", children: [
|
|
4284
4466
|
/* @__PURE__ */ jsxs28(Box27, { gap: SPACING.sm, marginBottom: SPACING.xs, children: [
|
|
4285
|
-
/* @__PURE__ */
|
|
4286
|
-
/* @__PURE__ */
|
|
4467
|
+
/* @__PURE__ */ jsx31(SectionHeader, { emoji: "\u{1F4DC}", title: t("history_title", { count: filtered.length }), gradient: GRADIENTS.gold }),
|
|
4468
|
+
/* @__PURE__ */ jsx31(Text29, { color: filter === "all" ? COLORS.text : COLORS.gold, children: t("history_filterLabel", { filter }) })
|
|
4287
4469
|
] }),
|
|
4288
|
-
isSearching && /* @__PURE__ */
|
|
4289
|
-
confirmClear && /* @__PURE__ */
|
|
4470
|
+
isSearching && /* @__PURE__ */ jsx31(Box27, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx31(SearchInput, { defaultValue: searchQuery, onChange: setSearchQuery, placeholder: t("history_searchPlaceholder"), isActive: true }) }),
|
|
4471
|
+
confirmClear && /* @__PURE__ */ jsx31(
|
|
4290
4472
|
ConfirmDialog,
|
|
4291
4473
|
{
|
|
4292
4474
|
message: t("history_confirmClear", { count: entries.length }),
|
|
@@ -4297,7 +4479,7 @@ function HistoryView() {
|
|
|
4297
4479
|
onCancel: () => setConfirmClear(false)
|
|
4298
4480
|
}
|
|
4299
4481
|
),
|
|
4300
|
-
confirmReplay && /* @__PURE__ */
|
|
4482
|
+
confirmReplay && /* @__PURE__ */ jsx31(
|
|
4301
4483
|
ConfirmDialog,
|
|
4302
4484
|
{
|
|
4303
4485
|
message: confirmReplay.action === "upgrade-all" ? t("history_replayAll") + "\n" + t("upgrade_all_warning") : t("history_confirmReplay", { action: t(ACTION_LABEL_KEYS[confirmReplay.action]), name: confirmReplay.packageName ?? "" }),
|
|
@@ -4325,8 +4507,16 @@ function HistoryView() {
|
|
|
4325
4507
|
onCancel: () => setConfirmReplay(null)
|
|
4326
4508
|
}
|
|
4327
4509
|
),
|
|
4328
|
-
(stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */
|
|
4329
|
-
|
|
4510
|
+
(stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx31(Box27, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx31(
|
|
4511
|
+
ProgressLog,
|
|
4512
|
+
{
|
|
4513
|
+
lines: stream.lines,
|
|
4514
|
+
isRunning: stream.isRunning,
|
|
4515
|
+
title: t("hint_replay"),
|
|
4516
|
+
maxVisible: streamRows
|
|
4517
|
+
}
|
|
4518
|
+
) }),
|
|
4519
|
+
filtered.length === 0 && !confirmClear && /* @__PURE__ */ jsx31(Text29, { color: COLORS.textSecondary, italic: true, children: filter !== "all" ? t("history_noEntriesFor", { filter }) : t("history_noEntries") }),
|
|
4330
4520
|
filtered.length > 0 && !confirmClear && /* @__PURE__ */ jsxs28(Box27, { flexDirection: "column", children: [
|
|
4331
4521
|
start > 0 && /* @__PURE__ */ jsxs28(Text29, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4332
4522
|
" ",
|
|
@@ -4338,18 +4528,18 @@ function HistoryView() {
|
|
|
4338
4528
|
const { icon, color } = ACTION_ICONS[entry.action];
|
|
4339
4529
|
const ts = new Date(entry.timestamp).getTime() / 1e3;
|
|
4340
4530
|
return /* @__PURE__ */ jsxs28(SelectableRow, { isCurrent, children: [
|
|
4341
|
-
/* @__PURE__ */
|
|
4342
|
-
/* @__PURE__ */
|
|
4343
|
-
/* @__PURE__ */
|
|
4344
|
-
entry.success ? /* @__PURE__ */
|
|
4345
|
-
/* @__PURE__ */
|
|
4531
|
+
/* @__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]).padEnd(12) }),
|
|
4533
|
+
/* @__PURE__ */ jsx31(Text29, { color: COLORS.text, children: entry.packageName ?? t("history_all") }),
|
|
4534
|
+
entry.success ? /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_ok"), variant: "success" }) : /* @__PURE__ */ jsx31(StatusBadge, { label: t("badge_fail"), variant: "error" }),
|
|
4535
|
+
/* @__PURE__ */ jsx31(Text29, { color: COLORS.muted, children: formatRelativeTime(ts) })
|
|
4346
4536
|
] }, entry.id);
|
|
4347
4537
|
}),
|
|
4348
4538
|
start + MAX_VISIBLE_ROWS < filtered.length && /* @__PURE__ */ jsxs28(Text29, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
4349
4539
|
" ",
|
|
4350
4540
|
t("scroll_moreBelow", { count: filtered.length - start - MAX_VISIBLE_ROWS })
|
|
4351
4541
|
] }),
|
|
4352
|
-
/* @__PURE__ */
|
|
4542
|
+
/* @__PURE__ */ jsx31(Box27, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs28(Text29, { color: COLORS.text, bold: true, children: [
|
|
4353
4543
|
cursor + 1,
|
|
4354
4544
|
"/",
|
|
4355
4545
|
filtered.length
|
|
@@ -4359,9 +4549,9 @@ function HistoryView() {
|
|
|
4359
4549
|
}
|
|
4360
4550
|
|
|
4361
4551
|
// src/views/security-audit.tsx
|
|
4362
|
-
import { useEffect as useEffect18, useState as
|
|
4552
|
+
import { useEffect as useEffect18, useState as useState15 } from "react";
|
|
4363
4553
|
import { Box as Box28, Text as Text30 } from "ink";
|
|
4364
|
-
import { jsx as
|
|
4554
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4365
4555
|
var SEVERITY_COLORS = {
|
|
4366
4556
|
CRITICAL: COLORS.error,
|
|
4367
4557
|
HIGH: COLORS.error,
|
|
@@ -4382,9 +4572,9 @@ function isNetworkError(msg) {
|
|
|
4382
4572
|
function SecurityAuditView() {
|
|
4383
4573
|
const { summary, loading, error, scan, cachedAt } = useSecurityStore();
|
|
4384
4574
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
4385
|
-
const [cursor, setCursor] =
|
|
4386
|
-
const [expandedPkg, setExpandedPkg] =
|
|
4387
|
-
const [confirmUpgrade, setConfirmUpgrade] =
|
|
4575
|
+
const [cursor, setCursor] = useState15(0);
|
|
4576
|
+
const [expandedPkg, setExpandedPkg] = useState15(null);
|
|
4577
|
+
const [confirmUpgrade, setConfirmUpgrade] = useState15(null);
|
|
4388
4578
|
const stream = useBrewStream();
|
|
4389
4579
|
useEffect18(() => {
|
|
4390
4580
|
scan();
|
|
@@ -4410,17 +4600,17 @@ function SecurityAuditView() {
|
|
|
4410
4600
|
setExpandedPkg(expandedPkg === results[cursor].packageName ? null : results[cursor].packageName);
|
|
4411
4601
|
}
|
|
4412
4602
|
});
|
|
4413
|
-
if (loading) return /* @__PURE__ */
|
|
4603
|
+
if (loading) return /* @__PURE__ */ jsx32(Loading, { message: t("loading_security") });
|
|
4414
4604
|
if (error) {
|
|
4415
4605
|
const displayError = isNetworkError(error) ? t("security_networkError") : error;
|
|
4416
|
-
return /* @__PURE__ */
|
|
4606
|
+
return /* @__PURE__ */ jsx32(ErrorMessage, { message: displayError });
|
|
4417
4607
|
}
|
|
4418
4608
|
const cacheAge = cachedAt ? formatRelativeTime(cachedAt / 1e3) : null;
|
|
4419
4609
|
return /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", children: [
|
|
4420
|
-
/* @__PURE__ */
|
|
4610
|
+
/* @__PURE__ */ jsx32(SectionHeader, { emoji: "\u{1F6E1}\uFE0F", title: t("security_title"), gradient: GRADIENTS.ocean }),
|
|
4421
4611
|
summary && /* @__PURE__ */ jsxs29(Box28, { gap: SPACING.xs, marginY: SPACING.xs, children: [
|
|
4422
|
-
/* @__PURE__ */
|
|
4423
|
-
/* @__PURE__ */
|
|
4612
|
+
/* @__PURE__ */ jsx32(StatCard, { label: t("security_scanned"), value: summary.totalPackages, color: COLORS.info }),
|
|
4613
|
+
/* @__PURE__ */ jsx32(
|
|
4424
4614
|
StatCard,
|
|
4425
4615
|
{
|
|
4426
4616
|
label: t("security_vulnerable"),
|
|
@@ -4428,14 +4618,14 @@ function SecurityAuditView() {
|
|
|
4428
4618
|
color: summary.vulnerablePackages > 0 ? COLORS.error : COLORS.success
|
|
4429
4619
|
}
|
|
4430
4620
|
),
|
|
4431
|
-
summary.criticalCount > 0 && /* @__PURE__ */
|
|
4432
|
-
summary.highCount > 0 && /* @__PURE__ */
|
|
4433
|
-
summary.mediumCount > 0 && /* @__PURE__ */
|
|
4621
|
+
summary.criticalCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_critical"), value: summary.criticalCount, color: COLORS.error }),
|
|
4622
|
+
summary.highCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_high"), value: summary.highCount, color: COLORS.error }),
|
|
4623
|
+
summary.mediumCount > 0 && /* @__PURE__ */ jsx32(StatCard, { label: t("security_medium"), value: summary.mediumCount, color: COLORS.warning })
|
|
4434
4624
|
] }),
|
|
4435
|
-
cacheAge && /* @__PURE__ */
|
|
4436
|
-
summary && /* @__PURE__ */
|
|
4437
|
-
results.length === 0 && summary && /* @__PURE__ */
|
|
4438
|
-
confirmUpgrade && /* @__PURE__ */
|
|
4625
|
+
cacheAge && /* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: t("security_cachedResults", { time: cacheAge }) }),
|
|
4626
|
+
summary && /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(Text30, { color: COLORS.textSecondary, italic: true, children: t("security_coverage_warning") }) }),
|
|
4627
|
+
results.length === 0 && summary && /* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(ResultBanner, { status: "success", message: `\u2714 ${t("security_noVulns")}` }) }),
|
|
4628
|
+
confirmUpgrade && /* @__PURE__ */ jsx32(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx32(
|
|
4439
4629
|
ConfirmDialog,
|
|
4440
4630
|
{
|
|
4441
4631
|
message: t("security_confirmUpgrade", { name: confirmUpgrade }),
|
|
@@ -4448,50 +4638,50 @@ function SecurityAuditView() {
|
|
|
4448
4638
|
onCancel: () => setConfirmUpgrade(null)
|
|
4449
4639
|
}
|
|
4450
4640
|
) }),
|
|
4451
|
-
(stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */
|
|
4641
|
+
(stream.isRunning || stream.lines.length > 0) && /* @__PURE__ */ jsx32(Box28, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx32(ProgressLog, { lines: stream.lines, isRunning: stream.isRunning, title: t("hint_upgrade") }) }),
|
|
4452
4642
|
results.length > 0 && /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
4453
4643
|
results.map((pkg, i) => {
|
|
4454
4644
|
const isCurrent = i === cursor;
|
|
4455
4645
|
const isExpanded = expandedPkg === pkg.packageName;
|
|
4456
4646
|
return /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", children: [
|
|
4457
4647
|
/* @__PURE__ */ jsxs29(SelectableRow, { isCurrent, children: [
|
|
4458
|
-
/* @__PURE__ */
|
|
4459
|
-
/* @__PURE__ */
|
|
4460
|
-
/* @__PURE__ */
|
|
4461
|
-
/* @__PURE__ */
|
|
4648
|
+
/* @__PURE__ */ jsx32(StatusBadge, { label: pkg.maxSeverity, variant: SEVERITY_BADGE[pkg.maxSeverity] }),
|
|
4649
|
+
/* @__PURE__ */ jsx32(Text30, { bold: isCurrent, inverse: isCurrent, color: isCurrent ? COLORS.text : COLORS.muted, children: pkg.packageName }),
|
|
4650
|
+
/* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: pkg.installedVersion }),
|
|
4651
|
+
/* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: tp("plural_vulns", pkg.vulnerabilities.length) }),
|
|
4462
4652
|
pkg.vulnerabilities.some((v) => v.fixedVersion) && /* @__PURE__ */ jsxs29(Text30, { color: COLORS.textSecondary, children: [
|
|
4463
4653
|
"[R:",
|
|
4464
4654
|
t("hint_rollback"),
|
|
4465
4655
|
"]"
|
|
4466
4656
|
] }),
|
|
4467
|
-
/* @__PURE__ */
|
|
4657
|
+
/* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, children: isExpanded ? "\u25BC" : "\u25B6" })
|
|
4468
4658
|
] }),
|
|
4469
|
-
isExpanded && /* @__PURE__ */
|
|
4659
|
+
isExpanded && /* @__PURE__ */ jsx32(Box28, { flexDirection: "column", paddingLeft: SPACING.lg, marginBottom: SPACING.xs, children: pkg.vulnerabilities.map((vuln) => /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", marginBottom: SPACING.xs, children: [
|
|
4470
4660
|
/* @__PURE__ */ jsxs29(Box28, { gap: SPACING.xs, children: [
|
|
4471
|
-
/* @__PURE__ */
|
|
4661
|
+
/* @__PURE__ */ jsx32(Text30, { color: SEVERITY_COLORS[vuln.severity], bold: true, children: vuln.id }),
|
|
4472
4662
|
/* @__PURE__ */ jsxs29(Text30, { color: COLORS.muted, children: [
|
|
4473
4663
|
"[",
|
|
4474
4664
|
vuln.severity,
|
|
4475
4665
|
"]"
|
|
4476
4666
|
] })
|
|
4477
4667
|
] }),
|
|
4478
|
-
/* @__PURE__ */
|
|
4479
|
-
vuln.fixedVersion && /* @__PURE__ */
|
|
4668
|
+
/* @__PURE__ */ jsx32(Text30, { color: COLORS.muted, wrap: "wrap", children: vuln.summary }),
|
|
4669
|
+
vuln.fixedVersion && /* @__PURE__ */ jsx32(Text30, { color: COLORS.success, children: t("security_fixedIn", { version: vuln.fixedVersion }) })
|
|
4480
4670
|
] }, vuln.id)) })
|
|
4481
4671
|
] }, pkg.packageName);
|
|
4482
4672
|
}),
|
|
4483
|
-
/* @__PURE__ */
|
|
4673
|
+
/* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs29(Text30, { color: COLORS.text, bold: true, children: [
|
|
4484
4674
|
cursor + 1,
|
|
4485
4675
|
"/",
|
|
4486
4676
|
results.length
|
|
4487
4677
|
] }) }),
|
|
4488
|
-
/* @__PURE__ */
|
|
4678
|
+
/* @__PURE__ */ jsx32(Box28, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx32(Text30, { color: COLORS.textSecondary, children: t("security_rollback_hint") }) })
|
|
4489
4679
|
] })
|
|
4490
4680
|
] });
|
|
4491
4681
|
}
|
|
4492
4682
|
|
|
4493
4683
|
// src/views/account.tsx
|
|
4494
|
-
import { useState as
|
|
4684
|
+
import { useState as useState16 } from "react";
|
|
4495
4685
|
import { Box as Box29, Text as Text31 } from "ink";
|
|
4496
4686
|
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4497
4687
|
|
|
@@ -4570,16 +4760,16 @@ async function redeemPromoCode(code) {
|
|
|
4570
4760
|
}
|
|
4571
4761
|
|
|
4572
4762
|
// src/views/account.tsx
|
|
4573
|
-
import { Fragment as Fragment5, jsx as
|
|
4763
|
+
import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
4574
4764
|
function AccountView() {
|
|
4575
4765
|
const { status, license, deactivate: deactivate2, revalidate: revalidate2, degradation } = useLicenseStore();
|
|
4576
|
-
const [confirmDeactivate, setConfirmDeactivate] =
|
|
4577
|
-
const [deactivating, setDeactivating] =
|
|
4578
|
-
const [deactivateError, setDeactivateError] =
|
|
4579
|
-
const [promoMode, setPromoMode] =
|
|
4580
|
-
const [promoLoading, setPromoLoading] =
|
|
4581
|
-
const [promoResult, setPromoResult] =
|
|
4582
|
-
const [revalidating, setRevalidating] =
|
|
4766
|
+
const [confirmDeactivate, setConfirmDeactivate] = useState16(false);
|
|
4767
|
+
const [deactivating, setDeactivating] = useState16(false);
|
|
4768
|
+
const [deactivateError, setDeactivateError] = useState16(null);
|
|
4769
|
+
const [promoMode, setPromoMode] = useState16(false);
|
|
4770
|
+
const [promoLoading, setPromoLoading] = useState16(false);
|
|
4771
|
+
const [promoResult, setPromoResult] = useState16(null);
|
|
4772
|
+
const [revalidating, setRevalidating] = useState16(false);
|
|
4583
4773
|
useViewInput((input, key) => {
|
|
4584
4774
|
if (confirmDeactivate || deactivating || promoMode || revalidating) {
|
|
4585
4775
|
if (key.escape && promoMode) {
|
|
@@ -4605,11 +4795,11 @@ function AccountView() {
|
|
|
4605
4795
|
return key.slice(0, 4) + "-****-****-" + key.slice(-4);
|
|
4606
4796
|
};
|
|
4607
4797
|
if (status === "validating") {
|
|
4608
|
-
return /* @__PURE__ */
|
|
4798
|
+
return /* @__PURE__ */ jsx33(Loading, { message: t("account_loading") });
|
|
4609
4799
|
}
|
|
4610
4800
|
return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", children: [
|
|
4611
|
-
/* @__PURE__ */
|
|
4612
|
-
confirmDeactivate && /* @__PURE__ */
|
|
4801
|
+
/* @__PURE__ */ jsx33(SectionHeader, { emoji: "\u{1F464}", title: t("account_title"), gradient: GRADIENTS.gold }),
|
|
4802
|
+
confirmDeactivate && /* @__PURE__ */ jsx33(Box29, { marginY: SPACING.xs, children: /* @__PURE__ */ jsx33(
|
|
4613
4803
|
ConfirmDialog,
|
|
4614
4804
|
{
|
|
4615
4805
|
message: t("account_confirmDeactivate"),
|
|
@@ -4630,70 +4820,68 @@ function AccountView() {
|
|
|
4630
4820
|
) }),
|
|
4631
4821
|
/* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.xs, paddingLeft: SPACING.sm, children: [
|
|
4632
4822
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4633
|
-
/* @__PURE__ */
|
|
4634
|
-
status === "pro" && /* @__PURE__ */
|
|
4635
|
-
status === "free" && /* @__PURE__ */
|
|
4636
|
-
status === "expired" && /* @__PURE__ */
|
|
4823
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_statusLabel") }),
|
|
4824
|
+
status === "pro" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: t("account_pro") }),
|
|
4825
|
+
status === "free" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_free") }),
|
|
4826
|
+
status === "expired" && /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: t("account_expired") })
|
|
4637
4827
|
] }),
|
|
4638
|
-
(degradation === "warning" || degradation === "limited") && license && /* @__PURE__ */
|
|
4828
|
+
(degradation === "warning" || degradation === "limited") && license && /* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.warning, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx33(Text31, { color: COLORS.warning, children: t("license_offlineWarning", {
|
|
4639
4829
|
days: Math.floor((Date.now() - new Date(license.lastValidatedAt).getTime()) / (24 * 60 * 60 * 1e3))
|
|
4640
4830
|
}) }) }),
|
|
4641
4831
|
license && /* @__PURE__ */ jsxs30(Fragment5, { children: [
|
|
4642
4832
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4643
|
-
/* @__PURE__ */
|
|
4644
|
-
/* @__PURE__ */
|
|
4833
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_emailLabel") }),
|
|
4834
|
+
/* @__PURE__ */ jsx33(Text31, { children: license.customerEmail })
|
|
4645
4835
|
] }),
|
|
4646
4836
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4647
|
-
/* @__PURE__ */
|
|
4648
|
-
/* @__PURE__ */
|
|
4837
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_nameLabel") }),
|
|
4838
|
+
/* @__PURE__ */ jsx33(Text31, { children: license.customerName })
|
|
4649
4839
|
] }),
|
|
4650
4840
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4651
|
-
/* @__PURE__ */
|
|
4652
|
-
/* @__PURE__ */
|
|
4841
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_planLabel") }),
|
|
4842
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: "Pro" })
|
|
4653
4843
|
] }),
|
|
4654
4844
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4655
|
-
/* @__PURE__ */
|
|
4656
|
-
/* @__PURE__ */
|
|
4845
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_keyLabel") }),
|
|
4846
|
+
/* @__PURE__ */ jsx33(Text31, { children: maskKey(license.key) })
|
|
4657
4847
|
] }),
|
|
4658
4848
|
license.expiresAt && /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4659
|
-
/* @__PURE__ */
|
|
4660
|
-
/* @__PURE__ */
|
|
4849
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_expiresLabel") }),
|
|
4850
|
+
/* @__PURE__ */ jsx33(Text31, { children: formatDate(license.expiresAt) })
|
|
4661
4851
|
] }),
|
|
4662
4852
|
/* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4663
|
-
/* @__PURE__ */
|
|
4664
|
-
/* @__PURE__ */
|
|
4853
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_activatedLabel") }),
|
|
4854
|
+
/* @__PURE__ */ jsx33(Text31, { children: formatDate(license.activatedAt) })
|
|
4665
4855
|
] })
|
|
4666
4856
|
] }),
|
|
4667
|
-
status === "free" && /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.
|
|
4857
|
+
status === "free" && /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", marginTop: SPACING.xs, borderStyle: "round", borderColor: COLORS.brand, paddingX: SPACING.sm, paddingY: SPACING.none, flexShrink: 1, children: [
|
|
4668
4858
|
/* @__PURE__ */ jsxs30(Text31, { bold: true, color: COLORS.brand, children: [
|
|
4669
4859
|
"\u2B50",
|
|
4670
4860
|
" ",
|
|
4671
4861
|
t("account_upgradeTitle")
|
|
4672
4862
|
] }),
|
|
4673
|
-
/* @__PURE__ */
|
|
4674
|
-
/* @__PURE__ */
|
|
4675
|
-
/* @__PURE__ */ jsx32(Text31, { color: COLORS.info, bold: true, children: t("account_pricing") }),
|
|
4676
|
-
/* @__PURE__ */ jsx32(Text31, { children: " " }),
|
|
4863
|
+
/* @__PURE__ */ jsx33(Text31, { wrap: "wrap", children: t("account_unlockDesc") }),
|
|
4864
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.info, bold: true, children: t("account_pricing") }),
|
|
4677
4865
|
/* @__PURE__ */ jsxs30(Text31, { color: COLORS.muted, children: [
|
|
4678
4866
|
t("upgrade_buyAt"),
|
|
4679
4867
|
" ",
|
|
4680
|
-
/* @__PURE__ */
|
|
4868
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, bold: true, children: t("upgrade_buyUrl") })
|
|
4681
4869
|
] }),
|
|
4682
4870
|
/* @__PURE__ */ jsxs30(Text31, { color: COLORS.muted, children: [
|
|
4683
4871
|
t("account_runActivate"),
|
|
4684
4872
|
" ",
|
|
4685
|
-
/* @__PURE__ */
|
|
4873
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.success, bold: true, children: t("account_activateCmd") })
|
|
4686
4874
|
] })
|
|
4687
4875
|
] }),
|
|
4688
|
-
status === "expired" && /* @__PURE__ */
|
|
4689
|
-
deactivating && /* @__PURE__ */
|
|
4690
|
-
deactivateError && /* @__PURE__ */
|
|
4876
|
+
status === "expired" && /* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx33(Box29, { borderStyle: "round", borderColor: COLORS.error, paddingX: SPACING.sm, paddingY: SPACING.none, children: /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: t("account_licenseExpired") }) }) }),
|
|
4877
|
+
deactivating && /* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, children: t("account_deactivating") }),
|
|
4878
|
+
deactivateError && /* @__PURE__ */ jsx33(Text31, { color: COLORS.error, children: deactivateError })
|
|
4691
4879
|
] }),
|
|
4692
|
-
/* @__PURE__ */
|
|
4693
|
-
/* @__PURE__ */
|
|
4694
|
-
promoLoading ? /* @__PURE__ */
|
|
4695
|
-
/* @__PURE__ */
|
|
4696
|
-
/* @__PURE__ */
|
|
4880
|
+
/* @__PURE__ */ jsx33(Box29, { flexDirection: "column", marginTop: SPACING.xs, paddingLeft: SPACING.sm, children: promoMode ? /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", gap: SPACING.xs, children: [
|
|
4881
|
+
/* @__PURE__ */ jsx33(Text31, { bold: true, color: COLORS.gold, children: t("account_promoTitle") }),
|
|
4882
|
+
promoLoading ? /* @__PURE__ */ jsx33(Text31, { color: COLORS.sky, children: t("account_promoValidating") }) : /* @__PURE__ */ jsxs30(Box29, { gap: SPACING.xs, children: [
|
|
4883
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.muted, children: t("account_promoLabel") }),
|
|
4884
|
+
/* @__PURE__ */ jsx33(
|
|
4697
4885
|
TextInput5,
|
|
4698
4886
|
{
|
|
4699
4887
|
defaultValue: "",
|
|
@@ -4717,21 +4905,21 @@ function AccountView() {
|
|
|
4717
4905
|
}
|
|
4718
4906
|
)
|
|
4719
4907
|
] }),
|
|
4720
|
-
promoResult && /* @__PURE__ */
|
|
4721
|
-
/* @__PURE__ */
|
|
4722
|
-
] }) : /* @__PURE__ */
|
|
4723
|
-
/* @__PURE__ */
|
|
4908
|
+
promoResult && /* @__PURE__ */ jsx33(ResultBanner, { status: promoResult.success ? "success" : "error", message: promoResult.message }),
|
|
4909
|
+
/* @__PURE__ */ jsx33(Text31, { color: COLORS.textSecondary, dimColor: true, children: t("account_promoEsc") })
|
|
4910
|
+
] }) : /* @__PURE__ */ jsx33(Text31, { color: COLORS.textSecondary, children: t("account_promoHint") }) }),
|
|
4911
|
+
/* @__PURE__ */ jsx33(Box29, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs30(Text31, { color: COLORS.textSecondary, children: [
|
|
4724
4912
|
status === "pro" || status === "team" ? `d ${t("hint_deactivate")} ` : "",
|
|
4725
4913
|
status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
|
|
4726
4914
|
revalidating ? t("account_revalidating") : "",
|
|
4727
4915
|
" ",
|
|
4728
|
-
t("app_version", { version: "
|
|
4916
|
+
t("app_version", { version: "1.1.0" })
|
|
4729
4917
|
] }) })
|
|
4730
4918
|
] });
|
|
4731
4919
|
}
|
|
4732
4920
|
|
|
4733
4921
|
// src/views/rollback.tsx
|
|
4734
|
-
import { useCallback as useCallback3, useEffect as useEffect19, useRef as
|
|
4922
|
+
import { useCallback as useCallback3, useEffect as useEffect19, useRef as useRef11, useState as useState17 } from "react";
|
|
4735
4923
|
import { Box as Box30, Text as Text32 } from "ink";
|
|
4736
4924
|
|
|
4737
4925
|
// src/stores/rollback-store.ts
|
|
@@ -4942,7 +5130,7 @@ var useRollbackStore = create12((set) => ({
|
|
|
4942
5130
|
}));
|
|
4943
5131
|
|
|
4944
5132
|
// src/views/rollback.tsx
|
|
4945
|
-
import { jsx as
|
|
5133
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
4946
5134
|
function strategyLabel(action) {
|
|
4947
5135
|
switch (action.strategy) {
|
|
4948
5136
|
case "versioned-formula":
|
|
@@ -4970,21 +5158,29 @@ function actionPrefix(action) {
|
|
|
4970
5158
|
}
|
|
4971
5159
|
function PlanView({ plan }) {
|
|
4972
5160
|
const executableCount = plan.actions.filter((a) => a.strategy !== "unavailable" && a.action !== "remove").length;
|
|
5161
|
+
const reservedForWarnings = Math.min(plan.warnings.length, 3) * 2;
|
|
5162
|
+
const actionsBudget = useVisibleRows({
|
|
5163
|
+
reservedRows: 6 + reservedForWarnings,
|
|
5164
|
+
fallbackReservedRows: 14 + reservedForWarnings,
|
|
5165
|
+
minRows: 2
|
|
5166
|
+
});
|
|
5167
|
+
const visibleActions = plan.actions.slice(0, actionsBudget);
|
|
5168
|
+
const hiddenActions = plan.actions.length - visibleActions.length;
|
|
4973
5169
|
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
4974
5170
|
/* @__PURE__ */ jsxs31(Box30, { marginBottom: SPACING.xs, children: [
|
|
4975
5171
|
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.text, bold: true, children: [
|
|
4976
5172
|
plan.snapshotLabel,
|
|
4977
5173
|
" "
|
|
4978
5174
|
] }),
|
|
4979
|
-
/* @__PURE__ */
|
|
5175
|
+
/* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, children: plan.snapshotDate })
|
|
4980
5176
|
] }),
|
|
4981
|
-
plan.actions.length === 0 && /* @__PURE__ */
|
|
4982
|
-
|
|
5177
|
+
plan.actions.length === 0 && /* @__PURE__ */ jsx34(ResultBanner, { status: "success", message: t("rollback_diff_empty") }),
|
|
5178
|
+
visibleActions.map((a) => /* @__PURE__ */ jsxs31(Box30, { children: [
|
|
4983
5179
|
/* @__PURE__ */ jsxs31(Text32, { color: actionColor(a), children: [
|
|
4984
5180
|
actionPrefix(a),
|
|
4985
5181
|
" "
|
|
4986
5182
|
] }),
|
|
4987
|
-
/* @__PURE__ */
|
|
5183
|
+
/* @__PURE__ */ jsx34(Text32, { color: actionColor(a), bold: true, children: a.packageName }),
|
|
4988
5184
|
a.fromVersion !== "" && a.toVersion !== "" && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
4989
5185
|
" ",
|
|
4990
5186
|
a.fromVersion,
|
|
@@ -4995,18 +5191,26 @@ function PlanView({ plan }) {
|
|
|
4995
5191
|
" install ",
|
|
4996
5192
|
a.toVersion
|
|
4997
5193
|
] }),
|
|
4998
|
-
a.fromVersion !== "" && a.toVersion === "" && /* @__PURE__ */
|
|
5194
|
+
a.fromVersion !== "" && a.toVersion === "" && /* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, children: " remove" }),
|
|
4999
5195
|
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.muted, dimColor: true, children: [
|
|
5000
5196
|
" [",
|
|
5001
5197
|
strategyLabel(a),
|
|
5002
5198
|
"]"
|
|
5003
5199
|
] })
|
|
5004
5200
|
] }, a.packageName + a.action)),
|
|
5005
|
-
|
|
5201
|
+
hiddenActions > 0 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5202
|
+
" ",
|
|
5203
|
+
t("scroll_moreBelow", { count: hiddenActions })
|
|
5204
|
+
] }),
|
|
5205
|
+
plan.warnings.slice(0, 3).map((w) => /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.warning, wrap: "wrap", children: [
|
|
5006
5206
|
"\u26A0 ",
|
|
5007
5207
|
w
|
|
5008
5208
|
] }) }, w)),
|
|
5009
|
-
|
|
5209
|
+
plan.warnings.length > 3 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5210
|
+
" ",
|
|
5211
|
+
t("common_andMore", { count: plan.warnings.length - 3 })
|
|
5212
|
+
] }),
|
|
5213
|
+
/* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: plan.canExecute ? /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
5010
5214
|
"enter:",
|
|
5011
5215
|
t("rollback_confirm", { count: String(executableCount) }),
|
|
5012
5216
|
" esc:",
|
|
@@ -5021,13 +5225,18 @@ function PlanView({ plan }) {
|
|
|
5021
5225
|
function RollbackView() {
|
|
5022
5226
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5023
5227
|
const { snapshots, loading, error, plan, planLoading, planError, fetchSnapshots, selectSnapshot, clearPlan } = useRollbackStore();
|
|
5024
|
-
const [cursor, setCursor] =
|
|
5025
|
-
const [phase, setPhase] =
|
|
5026
|
-
const [streamLines, setStreamLines] =
|
|
5027
|
-
const [streamRunning, setStreamRunning] =
|
|
5028
|
-
const [streamError, setStreamError] =
|
|
5029
|
-
const generatorRef =
|
|
5030
|
-
const mountedRef =
|
|
5228
|
+
const [cursor, setCursor] = useState17(0);
|
|
5229
|
+
const [phase, setPhase] = useState17("list");
|
|
5230
|
+
const [streamLines, setStreamLines] = useState17([]);
|
|
5231
|
+
const [streamRunning, setStreamRunning] = useState17(false);
|
|
5232
|
+
const [streamError, setStreamError] = useState17(null);
|
|
5233
|
+
const generatorRef = useRef11(null);
|
|
5234
|
+
const mountedRef = useRef11(true);
|
|
5235
|
+
const snapshotRows = useVisibleRows({
|
|
5236
|
+
reservedRows: 6,
|
|
5237
|
+
fallbackReservedRows: 14,
|
|
5238
|
+
minRows: 1
|
|
5239
|
+
});
|
|
5031
5240
|
useEffect19(() => {
|
|
5032
5241
|
mountedRef.current = true;
|
|
5033
5242
|
return () => {
|
|
@@ -5095,21 +5304,21 @@ function RollbackView() {
|
|
|
5095
5304
|
void fetchSnapshots(isPro());
|
|
5096
5305
|
}
|
|
5097
5306
|
});
|
|
5098
|
-
if (loading) return /* @__PURE__ */
|
|
5099
|
-
if (error) return /* @__PURE__ */
|
|
5307
|
+
if (loading) return /* @__PURE__ */ jsx34(Loading, { message: t("rollback_select_snapshot") });
|
|
5308
|
+
if (error) return /* @__PURE__ */ jsx34(ErrorMessage, { message: error });
|
|
5100
5309
|
if (phase === "executing") {
|
|
5101
|
-
return /* @__PURE__ */
|
|
5310
|
+
return /* @__PURE__ */ jsx34(Box30, { flexDirection: "column", children: /* @__PURE__ */ jsx34(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("rollback_executing") }) });
|
|
5102
5311
|
}
|
|
5103
5312
|
if (phase === "result") {
|
|
5104
5313
|
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5105
|
-
/* @__PURE__ */
|
|
5314
|
+
/* @__PURE__ */ jsx34(
|
|
5106
5315
|
ResultBanner,
|
|
5107
5316
|
{
|
|
5108
5317
|
status: streamError ? "error" : "success",
|
|
5109
5318
|
message: streamError ? t("rollback_error", { error: streamError }) : t("rollback_success")
|
|
5110
5319
|
}
|
|
5111
5320
|
),
|
|
5112
|
-
/* @__PURE__ */
|
|
5321
|
+
/* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
5113
5322
|
"r:",
|
|
5114
5323
|
t("hint_refresh"),
|
|
5115
5324
|
" esc:",
|
|
@@ -5118,30 +5327,47 @@ function RollbackView() {
|
|
|
5118
5327
|
] });
|
|
5119
5328
|
}
|
|
5120
5329
|
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
|
|
5121
|
-
/* @__PURE__ */
|
|
5122
|
-
snapshots.length === 0 && /* @__PURE__ */
|
|
5123
|
-
phase === "list" && snapshots.length > 0 &&
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
/* @__PURE__ */
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5330
|
+
/* @__PURE__ */ jsx34(SectionHeader, { emoji: "\u23EA", title: t("rollback_title"), gradient: GRADIENTS.gold }),
|
|
5331
|
+
snapshots.length === 0 && /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(ResultBanner, { status: "info", message: t("rollback_no_snapshots") }) }),
|
|
5332
|
+
phase === "list" && snapshots.length > 0 && (() => {
|
|
5333
|
+
const start = Math.max(0, cursor - Math.floor(snapshotRows / 2));
|
|
5334
|
+
const visible = snapshots.slice(start, start + snapshotRows);
|
|
5335
|
+
return /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5336
|
+
/* @__PURE__ */ jsx34(Text32, { color: COLORS.textSecondary, dimColor: true, children: t("rollback_select_snapshot") }),
|
|
5337
|
+
/* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5338
|
+
start > 0 && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5339
|
+
" ",
|
|
5340
|
+
t("scroll_moreAbove", { count: start })
|
|
5341
|
+
] }),
|
|
5342
|
+
visible.map((s, vi) => {
|
|
5343
|
+
const i = start + vi;
|
|
5344
|
+
return /* @__PURE__ */ jsxs31(SelectableRow, { isCurrent: i === cursor, children: [
|
|
5345
|
+
/* @__PURE__ */ jsx34(Text32, { bold: i === cursor, color: i === cursor ? COLORS.text : COLORS.muted, children: s.label ?? t("rollback_snapshot_auto") }),
|
|
5346
|
+
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, children: [
|
|
5347
|
+
" \u2014 ",
|
|
5348
|
+
new Date(s.capturedAt).toLocaleString()
|
|
5349
|
+
] }),
|
|
5350
|
+
/* @__PURE__ */ jsxs31(Text32, { color: COLORS.muted, dimColor: true, children: [
|
|
5351
|
+
" ",
|
|
5352
|
+
"(",
|
|
5353
|
+
tp("packages", s.formulae.length + s.casks.length),
|
|
5354
|
+
")"
|
|
5355
|
+
] })
|
|
5356
|
+
] }, s.capturedAt);
|
|
5357
|
+
}),
|
|
5358
|
+
start + snapshotRows < snapshots.length && /* @__PURE__ */ jsxs31(Text32, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5359
|
+
" ",
|
|
5360
|
+
t("scroll_moreBelow", { count: snapshots.length - start - snapshotRows })
|
|
5361
|
+
] })
|
|
5136
5362
|
] })
|
|
5137
|
-
] }
|
|
5138
|
-
|
|
5363
|
+
] });
|
|
5364
|
+
})(),
|
|
5139
5365
|
phase === "plan" && /* @__PURE__ */ jsxs31(Box30, { flexDirection: "column", children: [
|
|
5140
|
-
planLoading && /* @__PURE__ */
|
|
5141
|
-
planError && /* @__PURE__ */
|
|
5142
|
-
plan && !planLoading && /* @__PURE__ */
|
|
5366
|
+
planLoading && /* @__PURE__ */ jsx34(Loading, { message: t("rollback_capturing") }),
|
|
5367
|
+
planError && /* @__PURE__ */ jsx34(ErrorMessage, { message: planError }),
|
|
5368
|
+
plan && !planLoading && /* @__PURE__ */ jsx34(PlanView, { plan })
|
|
5143
5369
|
] }),
|
|
5144
|
-
phase === "confirm" && plan && /* @__PURE__ */
|
|
5370
|
+
phase === "confirm" && plan && /* @__PURE__ */ jsx34(Box30, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx34(
|
|
5145
5371
|
ConfirmDialog,
|
|
5146
5372
|
{
|
|
5147
5373
|
message: t("rollback_confirm", {
|
|
@@ -5155,10 +5381,10 @@ function RollbackView() {
|
|
|
5155
5381
|
}
|
|
5156
5382
|
|
|
5157
5383
|
// src/views/brewfile.tsx
|
|
5158
|
-
import { useCallback as useCallback4, useEffect as useEffect20, useRef as
|
|
5384
|
+
import { useCallback as useCallback4, useEffect as useEffect20, useRef as useRef12, useState as useState18 } from "react";
|
|
5159
5385
|
import { Box as Box31, Text as Text33 } from "ink";
|
|
5160
5386
|
import { TextInput as TextInput6 } from "@inkjs/ui";
|
|
5161
|
-
import { jsx as
|
|
5387
|
+
import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5162
5388
|
function DriftScore({ score }) {
|
|
5163
5389
|
const color = score >= 80 ? COLORS.success : score >= 50 ? COLORS.warning : COLORS.error;
|
|
5164
5390
|
const bars = Math.round(score / 10);
|
|
@@ -5174,40 +5400,40 @@ function DriftScore({ score }) {
|
|
|
5174
5400
|
score,
|
|
5175
5401
|
"% "
|
|
5176
5402
|
] }),
|
|
5177
|
-
/* @__PURE__ */
|
|
5403
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.textSecondary, children: t("brewfile_compliant") })
|
|
5178
5404
|
] });
|
|
5179
5405
|
}
|
|
5180
5406
|
function DriftSummary({ drift }) {
|
|
5181
5407
|
return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5182
5408
|
drift.missingPackages.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
|
|
5183
|
-
/* @__PURE__ */
|
|
5184
|
-
/* @__PURE__ */
|
|
5409
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.error, children: "\u25CF " }),
|
|
5410
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.error, children: t("brewfile_drift_missing", { count: drift.missingPackages.length }) }),
|
|
5185
5411
|
/* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
|
|
5186
5412
|
": " + drift.missingPackages.slice(0, 3).join(", "),
|
|
5187
5413
|
drift.missingPackages.length > 3 ? "..." : ""
|
|
5188
5414
|
] })
|
|
5189
5415
|
] }),
|
|
5190
5416
|
drift.extraPackages.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
|
|
5191
|
-
/* @__PURE__ */
|
|
5192
|
-
/* @__PURE__ */
|
|
5417
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.warning, children: "\u25CF " }),
|
|
5418
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.warning, children: t("brewfile_drift_extra", { count: drift.extraPackages.length }) })
|
|
5193
5419
|
] }),
|
|
5194
5420
|
drift.wrongVersions.length > 0 && /* @__PURE__ */ jsxs32(Box31, { children: [
|
|
5195
|
-
/* @__PURE__ */
|
|
5196
|
-
/* @__PURE__ */
|
|
5421
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.info, children: "\u25CF " }),
|
|
5422
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.info, children: t("brewfile_drift_wrong", { count: drift.wrongVersions.length }) })
|
|
5197
5423
|
] }),
|
|
5198
|
-
drift.missingPackages.length === 0 && drift.extraPackages.length === 0 && drift.wrongVersions.length === 0 && /* @__PURE__ */
|
|
5424
|
+
drift.missingPackages.length === 0 && drift.extraPackages.length === 0 && drift.wrongVersions.length === 0 && /* @__PURE__ */ jsx35(ResultBanner, { status: "success", message: t("brewfile_in_sync") })
|
|
5199
5425
|
] });
|
|
5200
5426
|
}
|
|
5201
5427
|
function BrewfileView() {
|
|
5202
5428
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5203
5429
|
const { schema, drift, loading, driftLoading, error, load, createFromCurrent } = useBrewfileStore();
|
|
5204
|
-
const [phase, setPhase] =
|
|
5205
|
-
const [streamLines, setStreamLines] =
|
|
5206
|
-
const [streamRunning, setStreamRunning] =
|
|
5207
|
-
const [streamError, setStreamError] =
|
|
5208
|
-
const [resultMessage, setResultMessage] =
|
|
5209
|
-
const generatorRef =
|
|
5210
|
-
const mountedRef =
|
|
5430
|
+
const [phase, setPhase] = useState18("overview");
|
|
5431
|
+
const [streamLines, setStreamLines] = useState18([]);
|
|
5432
|
+
const [streamRunning, setStreamRunning] = useState18(false);
|
|
5433
|
+
const [streamError, setStreamError] = useState18(null);
|
|
5434
|
+
const [resultMessage, setResultMessage] = useState18("");
|
|
5435
|
+
const generatorRef = useRef12(null);
|
|
5436
|
+
const mountedRef = useRef12(true);
|
|
5211
5437
|
useEffect20(() => {
|
|
5212
5438
|
mountedRef.current = true;
|
|
5213
5439
|
void load();
|
|
@@ -5275,10 +5501,10 @@ function BrewfileView() {
|
|
|
5275
5501
|
if (key.escape) {
|
|
5276
5502
|
}
|
|
5277
5503
|
});
|
|
5278
|
-
if (loading) return /* @__PURE__ */
|
|
5279
|
-
if (error) return /* @__PURE__ */
|
|
5504
|
+
if (loading) return /* @__PURE__ */ jsx35(Loading, { message: t("loading_default") });
|
|
5505
|
+
if (error) return /* @__PURE__ */ jsx35(ErrorMessage, { message: error });
|
|
5280
5506
|
if (phase === "confirming-reconcile" && drift) {
|
|
5281
|
-
return /* @__PURE__ */
|
|
5507
|
+
return /* @__PURE__ */ jsx35(
|
|
5282
5508
|
ConfirmDialog,
|
|
5283
5509
|
{
|
|
5284
5510
|
message: t("confirm_brewfile_reconcile", {
|
|
@@ -5296,13 +5522,13 @@ function BrewfileView() {
|
|
|
5296
5522
|
}
|
|
5297
5523
|
if (phase === "creating") {
|
|
5298
5524
|
return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5299
|
-
/* @__PURE__ */
|
|
5525
|
+
/* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
|
|
5300
5526
|
/* @__PURE__ */ jsxs32(Box31, { marginTop: SPACING.xs, children: [
|
|
5301
5527
|
/* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
|
|
5302
5528
|
t("brewfile_create_name"),
|
|
5303
5529
|
" "
|
|
5304
5530
|
] }),
|
|
5305
|
-
/* @__PURE__ */
|
|
5531
|
+
/* @__PURE__ */ jsx35(
|
|
5306
5532
|
TextInput6,
|
|
5307
5533
|
{
|
|
5308
5534
|
defaultValue: "My Environment",
|
|
@@ -5318,7 +5544,7 @@ function BrewfileView() {
|
|
|
5318
5544
|
] });
|
|
5319
5545
|
}
|
|
5320
5546
|
if (phase === "reconciling") {
|
|
5321
|
-
return /* @__PURE__ */
|
|
5547
|
+
return /* @__PURE__ */ jsx35(Box31, { flexDirection: "column", children: /* @__PURE__ */ jsx35(
|
|
5322
5548
|
ProgressLog,
|
|
5323
5549
|
{
|
|
5324
5550
|
lines: streamLines,
|
|
@@ -5329,14 +5555,14 @@ function BrewfileView() {
|
|
|
5329
5555
|
}
|
|
5330
5556
|
if (phase === "result") {
|
|
5331
5557
|
return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5332
|
-
/* @__PURE__ */
|
|
5558
|
+
/* @__PURE__ */ jsx35(
|
|
5333
5559
|
ResultBanner,
|
|
5334
5560
|
{
|
|
5335
5561
|
status: streamError ? "error" : "success",
|
|
5336
5562
|
message: resultMessage
|
|
5337
5563
|
}
|
|
5338
5564
|
),
|
|
5339
|
-
/* @__PURE__ */
|
|
5565
|
+
/* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
|
|
5340
5566
|
"r:",
|
|
5341
5567
|
t("hint_refresh"),
|
|
5342
5568
|
" esc:",
|
|
@@ -5345,17 +5571,17 @@ function BrewfileView() {
|
|
|
5345
5571
|
] });
|
|
5346
5572
|
}
|
|
5347
5573
|
return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", children: [
|
|
5348
|
-
/* @__PURE__ */
|
|
5574
|
+
/* @__PURE__ */ jsx35(SectionHeader, { emoji: "\u{1F4E6}", title: t("brewfile_title"), gradient: GRADIENTS.ocean }),
|
|
5349
5575
|
schema === null ? /* @__PURE__ */ jsxs32(Box31, { marginTop: SPACING.xs, flexDirection: "column", children: [
|
|
5350
|
-
/* @__PURE__ */
|
|
5351
|
-
/* @__PURE__ */
|
|
5576
|
+
/* @__PURE__ */ jsx35(ResultBanner, { status: "info", message: t("brewfile_no_brewfile") }),
|
|
5577
|
+
/* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
|
|
5352
5578
|
"n:",
|
|
5353
5579
|
t("hint_new")
|
|
5354
5580
|
] }) })
|
|
5355
5581
|
] }) : /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5356
5582
|
/* @__PURE__ */ jsxs32(Box31, { gap: SPACING.sm, children: [
|
|
5357
|
-
/* @__PURE__ */
|
|
5358
|
-
schema.meta.description && /* @__PURE__ */
|
|
5583
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.text, bold: true, children: schema.meta.name }),
|
|
5584
|
+
schema.meta.description && /* @__PURE__ */ jsx35(Text33, { color: COLORS.textSecondary, children: schema.meta.description }),
|
|
5359
5585
|
schema.strictMode && /* @__PURE__ */ jsxs32(Text33, { color: COLORS.warning, children: [
|
|
5360
5586
|
"[",
|
|
5361
5587
|
t("brewfile_strict_mode"),
|
|
@@ -5363,15 +5589,15 @@ function BrewfileView() {
|
|
|
5363
5589
|
] })
|
|
5364
5590
|
] }),
|
|
5365
5591
|
/* @__PURE__ */ jsxs32(Box31, { gap: SPACING.md, marginTop: SPACING.xs, children: [
|
|
5366
|
-
/* @__PURE__ */
|
|
5367
|
-
/* @__PURE__ */
|
|
5592
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.sky, children: t("brewfile_formulae_count", { count: schema.formulae.length }) }),
|
|
5593
|
+
/* @__PURE__ */ jsx35(Text33, { color: COLORS.teal, children: t("brewfile_casks_count", { count: schema.casks.length }) })
|
|
5368
5594
|
] }),
|
|
5369
|
-
driftLoading && /* @__PURE__ */
|
|
5595
|
+
driftLoading && /* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx35(Text33, { color: COLORS.muted, children: t("brewfile_computing_drift") }) }),
|
|
5370
5596
|
drift && !driftLoading && /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5371
|
-
/* @__PURE__ */
|
|
5372
|
-
/* @__PURE__ */
|
|
5597
|
+
/* @__PURE__ */ jsx35(DriftScore, { score: drift.score }),
|
|
5598
|
+
/* @__PURE__ */ jsx35(DriftSummary, { drift })
|
|
5373
5599
|
] }),
|
|
5374
|
-
/* @__PURE__ */
|
|
5600
|
+
/* @__PURE__ */ jsx35(Box31, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs32(Text33, { color: COLORS.textSecondary, children: [
|
|
5375
5601
|
"r:",
|
|
5376
5602
|
t("hint_refresh"),
|
|
5377
5603
|
drift && (drift.missingPackages.length > 0 || drift.wrongVersions.length > 0) ? ` c:${t("hint_reconcile")}` : "",
|
|
@@ -5384,9 +5610,9 @@ function BrewfileView() {
|
|
|
5384
5610
|
}
|
|
5385
5611
|
|
|
5386
5612
|
// src/views/sync.tsx
|
|
5387
|
-
import { useCallback as useCallback5, useEffect as useEffect21, useState as
|
|
5613
|
+
import { useCallback as useCallback5, useEffect as useEffect21, useState as useState19 } from "react";
|
|
5388
5614
|
import { Box as Box32, Text as Text34 } from "ink";
|
|
5389
|
-
import { Fragment as Fragment6, jsx as
|
|
5615
|
+
import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5390
5616
|
function OverviewSection({
|
|
5391
5617
|
config,
|
|
5392
5618
|
lastResult,
|
|
@@ -5398,17 +5624,17 @@ function OverviewSection({
|
|
|
5398
5624
|
const showComplianceHint = !hasConflicts && !!lastResult?.success;
|
|
5399
5625
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5400
5626
|
config ? /* @__PURE__ */ jsxs33(Fragment6, { children: [
|
|
5401
|
-
/* @__PURE__ */
|
|
5402
|
-
config.lastSync && /* @__PURE__ */
|
|
5403
|
-
hasConflicts ? /* @__PURE__ */
|
|
5627
|
+
/* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_machine", { name: config.machineName }) }) }),
|
|
5628
|
+
config.lastSync && /* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_last_sync", { date: new Date(config.lastSync).toLocaleString() }) }) }),
|
|
5629
|
+
hasConflicts ? /* @__PURE__ */ jsx36(
|
|
5404
5630
|
ResultBanner,
|
|
5405
5631
|
{
|
|
5406
5632
|
status: "error",
|
|
5407
5633
|
message: t("sync_status_conflict", { count: String(conflicts.length) })
|
|
5408
5634
|
}
|
|
5409
|
-
) : lastResult?.success ? /* @__PURE__ */
|
|
5410
|
-
] }) : /* @__PURE__ */
|
|
5411
|
-
/* @__PURE__ */
|
|
5635
|
+
) : lastResult?.success ? /* @__PURE__ */ jsx36(ResultBanner, { status: "success", message: t("sync_status_ok") }) : null
|
|
5636
|
+
] }) : /* @__PURE__ */ jsx36(Box32, { marginBottom: SPACING.xs, children: /* @__PURE__ */ jsx36(Text34, { color: COLORS.textSecondary, children: t("sync_disabled") }) }),
|
|
5637
|
+
/* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
|
|
5412
5638
|
"s",
|
|
5413
5639
|
/* @__PURE__ */ jsxs33(Text34, { color: COLORS.gold, children: [
|
|
5414
5640
|
":",
|
|
@@ -5435,13 +5661,27 @@ function ConflictsList({
|
|
|
5435
5661
|
entries,
|
|
5436
5662
|
cursor
|
|
5437
5663
|
}) {
|
|
5664
|
+
const availableRows = useVisibleRows({
|
|
5665
|
+
reservedRows: 8,
|
|
5666
|
+
fallbackReservedRows: 14,
|
|
5667
|
+
minRows: 4
|
|
5668
|
+
});
|
|
5669
|
+
const perEntryRows = 4;
|
|
5670
|
+
const maxEntries = Math.max(1, Math.floor(availableRows / perEntryRows));
|
|
5671
|
+
const start = Math.max(0, cursor - Math.floor(maxEntries / 2));
|
|
5672
|
+
const visible = entries.slice(start, start + maxEntries);
|
|
5438
5673
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5439
|
-
|
|
5674
|
+
start > 0 && /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5675
|
+
" ",
|
|
5676
|
+
t("scroll_moreAbove", { count: start })
|
|
5677
|
+
] }),
|
|
5678
|
+
visible.map((entry, vi) => {
|
|
5679
|
+
const i = start + vi;
|
|
5440
5680
|
const { conflict, resolution } = entry;
|
|
5441
5681
|
const isActive = i === cursor;
|
|
5442
5682
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginBottom: SPACING.xs, children: [
|
|
5443
5683
|
/* @__PURE__ */ jsxs33(SelectableRow, { isCurrent: isActive, children: [
|
|
5444
|
-
/* @__PURE__ */
|
|
5684
|
+
/* @__PURE__ */ jsx36(Text34, { bold: true, color: isActive ? COLORS.text : COLORS.textSecondary, children: t("sync_conflict_title", { package: conflict.packageName }) }),
|
|
5445
5685
|
/* @__PURE__ */ jsxs33(Text34, { color: COLORS.muted, children: [
|
|
5446
5686
|
" (",
|
|
5447
5687
|
conflict.packageType,
|
|
@@ -5474,7 +5714,11 @@ function ConflictsList({
|
|
|
5474
5714
|
] })
|
|
5475
5715
|
] }, `${conflict.packageName}-${conflict.remoteMachine}`);
|
|
5476
5716
|
}),
|
|
5477
|
-
|
|
5717
|
+
start + maxEntries < entries.length && /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
5718
|
+
" ",
|
|
5719
|
+
t("scroll_moreBelow", { count: entries.length - start - maxEntries })
|
|
5720
|
+
] }),
|
|
5721
|
+
/* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
|
|
5478
5722
|
"j/k:",
|
|
5479
5723
|
t("hint_navigate"),
|
|
5480
5724
|
" l:",
|
|
@@ -5492,10 +5736,10 @@ function SyncView() {
|
|
|
5492
5736
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5493
5737
|
const navigate = useNavigationStore((s) => s.navigate);
|
|
5494
5738
|
const { config, lastResult, conflicts, loading, error, initialize, syncNow, resolveConflicts } = useSyncStore();
|
|
5495
|
-
const [phase, setPhase] =
|
|
5496
|
-
const [syncError, setSyncError] =
|
|
5497
|
-
const [conflictEntries, setConflictEntries] =
|
|
5498
|
-
const [cursor, setCursor] =
|
|
5739
|
+
const [phase, setPhase] = useState19("overview");
|
|
5740
|
+
const [syncError, setSyncError] = useState19(null);
|
|
5741
|
+
const [conflictEntries, setConflictEntries] = useState19([]);
|
|
5742
|
+
const [cursor, setCursor] = useState19(0);
|
|
5499
5743
|
useEffect21(() => {
|
|
5500
5744
|
void initialize(isPro());
|
|
5501
5745
|
}, []);
|
|
@@ -5591,7 +5835,7 @@ function SyncView() {
|
|
|
5591
5835
|
}
|
|
5592
5836
|
});
|
|
5593
5837
|
if (phase === "confirming-sync") {
|
|
5594
|
-
return /* @__PURE__ */
|
|
5838
|
+
return /* @__PURE__ */ jsx36(
|
|
5595
5839
|
ConfirmDialog,
|
|
5596
5840
|
{
|
|
5597
5841
|
message: t("confirm_sync_now"),
|
|
@@ -5605,7 +5849,7 @@ function SyncView() {
|
|
|
5605
5849
|
);
|
|
5606
5850
|
}
|
|
5607
5851
|
if (phase === "confirming-apply") {
|
|
5608
|
-
return /* @__PURE__ */
|
|
5852
|
+
return /* @__PURE__ */ jsx36(
|
|
5609
5853
|
ConfirmDialog,
|
|
5610
5854
|
{
|
|
5611
5855
|
message: t("confirm_sync_apply", { count: String(conflictEntries.length) }),
|
|
@@ -5619,20 +5863,20 @@ function SyncView() {
|
|
|
5619
5863
|
);
|
|
5620
5864
|
}
|
|
5621
5865
|
if (phase === "syncing" || loading) {
|
|
5622
|
-
return /* @__PURE__ */
|
|
5866
|
+
return /* @__PURE__ */ jsx36(Loading, { message: t("sync_syncing") });
|
|
5623
5867
|
}
|
|
5624
5868
|
if (phase === "result") {
|
|
5625
5869
|
const isError = !!(syncError ?? error);
|
|
5626
5870
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5627
|
-
/* @__PURE__ */
|
|
5628
|
-
/* @__PURE__ */
|
|
5871
|
+
/* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
|
|
5872
|
+
/* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(
|
|
5629
5873
|
ResultBanner,
|
|
5630
5874
|
{
|
|
5631
5875
|
status: isError ? "error" : "success",
|
|
5632
5876
|
message: isError ? t("sync_error", { error: syncError ?? error ?? "" }) : t("sync_success")
|
|
5633
5877
|
}
|
|
5634
5878
|
) }),
|
|
5635
|
-
/* @__PURE__ */
|
|
5879
|
+
/* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs33(Text34, { color: COLORS.textSecondary, children: [
|
|
5636
5880
|
"r:",
|
|
5637
5881
|
t("hint_refresh"),
|
|
5638
5882
|
" esc:",
|
|
@@ -5641,9 +5885,9 @@ function SyncView() {
|
|
|
5641
5885
|
] });
|
|
5642
5886
|
}
|
|
5643
5887
|
return /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", children: [
|
|
5644
|
-
/* @__PURE__ */
|
|
5645
|
-
error && phase === "overview" && /* @__PURE__ */
|
|
5646
|
-
phase === "overview" && /* @__PURE__ */
|
|
5888
|
+
/* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u{1F504}", title: t("sync_title"), gradient: GRADIENTS.gold }),
|
|
5889
|
+
error && phase === "overview" && /* @__PURE__ */ jsx36(Box32, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx36(ResultBanner, { status: "error", message: t("sync_error", { error }) }) }),
|
|
5890
|
+
phase === "overview" && /* @__PURE__ */ jsx36(
|
|
5647
5891
|
OverviewSection,
|
|
5648
5892
|
{
|
|
5649
5893
|
config,
|
|
@@ -5657,14 +5901,14 @@ function SyncView() {
|
|
|
5657
5901
|
}
|
|
5658
5902
|
),
|
|
5659
5903
|
phase === "conflicts" && /* @__PURE__ */ jsxs33(Box32, { flexDirection: "column", children: [
|
|
5660
|
-
/* @__PURE__ */
|
|
5661
|
-
/* @__PURE__ */
|
|
5904
|
+
/* @__PURE__ */ jsx36(SectionHeader, { emoji: "\u26A0", title: t("sync_status_conflict", { count: String(conflictEntries.length) }), gradient: GRADIENTS.gold }),
|
|
5905
|
+
/* @__PURE__ */ jsx36(ConflictsList, { entries: conflictEntries, cursor })
|
|
5662
5906
|
] })
|
|
5663
5907
|
] });
|
|
5664
5908
|
}
|
|
5665
5909
|
|
|
5666
5910
|
// src/views/compliance.tsx
|
|
5667
|
-
import { useCallback as useCallback6, useEffect as useEffect22, useRef as
|
|
5911
|
+
import { useCallback as useCallback6, useEffect as useEffect22, useRef as useRef13, useState as useState20 } from "react";
|
|
5668
5912
|
import { Box as Box33, Text as Text35 } from "ink";
|
|
5669
5913
|
import { TextInput as TextInput7 } from "@inkjs/ui";
|
|
5670
5914
|
|
|
@@ -5710,7 +5954,7 @@ async function* remediateViolations(violations, isPro) {
|
|
|
5710
5954
|
|
|
5711
5955
|
// src/views/compliance.tsx
|
|
5712
5956
|
import { join as join4 } from "path";
|
|
5713
|
-
import { jsx as
|
|
5957
|
+
import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5714
5958
|
function ComplianceScore({ report }) {
|
|
5715
5959
|
const color = report.score >= 80 ? COLORS.success : report.score >= 50 ? COLORS.warning : COLORS.error;
|
|
5716
5960
|
const bars = Math.round(report.score / 10);
|
|
@@ -5745,38 +5989,58 @@ function ViolationItem({ violation }) {
|
|
|
5745
5989
|
prefix,
|
|
5746
5990
|
" "
|
|
5747
5991
|
] }),
|
|
5748
|
-
/* @__PURE__ */
|
|
5992
|
+
/* @__PURE__ */ jsx37(Text35, { color, wrap: "wrap", children: violation.detail })
|
|
5749
5993
|
] });
|
|
5750
5994
|
}
|
|
5751
5995
|
function ViolationList({ violations }) {
|
|
5752
5996
|
const errors = violations.filter((v) => v.severity === "error");
|
|
5753
5997
|
const warnings = violations.filter((v) => v.severity === "warning");
|
|
5998
|
+
const totalRows = useVisibleRows({
|
|
5999
|
+
reservedRows: 11,
|
|
6000
|
+
fallbackReservedRows: 18,
|
|
6001
|
+
minRows: 2
|
|
6002
|
+
});
|
|
6003
|
+
const total = errors.length + warnings.length;
|
|
6004
|
+
const errorBudget = total === 0 ? 0 : Math.min(errors.length, Math.max(1, Math.round(errors.length / total * totalRows)));
|
|
6005
|
+
const warningBudget = Math.max(0, totalRows - errorBudget);
|
|
6006
|
+
const visibleErrors = errors.slice(0, errorBudget);
|
|
6007
|
+
const visibleWarnings = warnings.slice(0, warningBudget);
|
|
6008
|
+
const errorsHidden = errors.length - visibleErrors.length;
|
|
6009
|
+
const warningsHidden = warnings.length - visibleWarnings.length;
|
|
5754
6010
|
return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5755
6011
|
errors.length > 0 && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginBottom: SPACING.xs, children: [
|
|
5756
6012
|
/* @__PURE__ */ jsxs34(Text35, { color: COLORS.error, bold: true, children: [
|
|
5757
6013
|
t("compliance_violations", { count: String(errors.length) }),
|
|
5758
6014
|
" (errors)"
|
|
5759
6015
|
] }),
|
|
5760
|
-
|
|
6016
|
+
visibleErrors.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`)),
|
|
6017
|
+
errorsHidden > 0 && /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
6018
|
+
" ",
|
|
6019
|
+
t("scroll_moreBelow", { count: errorsHidden })
|
|
6020
|
+
] })
|
|
5761
6021
|
] }),
|
|
5762
6022
|
warnings.length > 0 && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
|
|
5763
6023
|
/* @__PURE__ */ jsxs34(Text35, { color: COLORS.warning, bold: true, children: [
|
|
5764
6024
|
t("compliance_violations", { count: String(warnings.length) }),
|
|
5765
6025
|
" (warnings)"
|
|
5766
6026
|
] }),
|
|
5767
|
-
|
|
6027
|
+
visibleWarnings.map((v) => /* @__PURE__ */ jsx37(ViolationItem, { violation: v }, `${v.type}-${v.packageName}`)),
|
|
6028
|
+
warningsHidden > 0 && /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, dimColor: true, children: [
|
|
6029
|
+
" ",
|
|
6030
|
+
t("scroll_moreBelow", { count: warningsHidden })
|
|
6031
|
+
] })
|
|
5768
6032
|
] })
|
|
5769
6033
|
] });
|
|
5770
6034
|
}
|
|
5771
6035
|
function ComplianceView() {
|
|
5772
6036
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5773
6037
|
const { policy, report, loading, error, importPolicy, runCheck } = useComplianceStore();
|
|
5774
|
-
const [phase, setPhase] =
|
|
5775
|
-
const [resultMessage, setResultMessage] =
|
|
5776
|
-
const [streamLines, setStreamLines] =
|
|
5777
|
-
const [streamRunning, setStreamRunning] =
|
|
5778
|
-
const generatorRef =
|
|
5779
|
-
const mountedRef =
|
|
6038
|
+
const [phase, setPhase] = useState20("overview");
|
|
6039
|
+
const [resultMessage, setResultMessage] = useState20(null);
|
|
6040
|
+
const [streamLines, setStreamLines] = useState20([]);
|
|
6041
|
+
const [streamRunning, setStreamRunning] = useState20(false);
|
|
6042
|
+
const generatorRef = useRef13(null);
|
|
6043
|
+
const mountedRef = useRef13(true);
|
|
5780
6044
|
useEffect22(() => {
|
|
5781
6045
|
mountedRef.current = true;
|
|
5782
6046
|
return () => {
|
|
@@ -5889,7 +6153,7 @@ function ComplianceView() {
|
|
|
5889
6153
|
const actionable = report.violations.filter(
|
|
5890
6154
|
(v) => v.type === "missing" || v.type === "wrong-version"
|
|
5891
6155
|
);
|
|
5892
|
-
return /* @__PURE__ */
|
|
6156
|
+
return /* @__PURE__ */ jsx37(
|
|
5893
6157
|
ConfirmDialog,
|
|
5894
6158
|
{
|
|
5895
6159
|
message: t("confirm_compliance_remediate", { count: String(actionable.length) }),
|
|
@@ -5905,23 +6169,23 @@ function ComplianceView() {
|
|
|
5905
6169
|
if (phase === "remediating" || loading && phase !== "importing") {
|
|
5906
6170
|
if (phase === "remediating") {
|
|
5907
6171
|
return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
|
|
5908
|
-
/* @__PURE__ */
|
|
5909
|
-
/* @__PURE__ */
|
|
6172
|
+
/* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
|
|
6173
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(ProgressLog, { lines: streamLines, isRunning: streamRunning, title: t("compliance_remediating") }) })
|
|
5910
6174
|
] });
|
|
5911
6175
|
}
|
|
5912
|
-
return /* @__PURE__ */
|
|
6176
|
+
return /* @__PURE__ */ jsx37(Loading, { message: t("compliance_title") });
|
|
5913
6177
|
}
|
|
5914
6178
|
if (phase === "result" && resultMessage) {
|
|
5915
6179
|
return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5916
|
-
/* @__PURE__ */
|
|
5917
|
-
/* @__PURE__ */
|
|
6180
|
+
/* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
|
|
6181
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(
|
|
5918
6182
|
ResultBanner,
|
|
5919
6183
|
{
|
|
5920
6184
|
status: resultMessage.ok ? "success" : "error",
|
|
5921
6185
|
message: resultMessage.text
|
|
5922
6186
|
}
|
|
5923
6187
|
) }),
|
|
5924
|
-
/* @__PURE__ */
|
|
6188
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
|
|
5925
6189
|
"r:",
|
|
5926
6190
|
t("hint_refresh"),
|
|
5927
6191
|
" esc:",
|
|
@@ -5930,11 +6194,11 @@ function ComplianceView() {
|
|
|
5930
6194
|
] });
|
|
5931
6195
|
}
|
|
5932
6196
|
return /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
|
|
5933
|
-
/* @__PURE__ */
|
|
5934
|
-
error && /* @__PURE__ */
|
|
6197
|
+
/* @__PURE__ */ jsx37(SectionHeader, { emoji: "\u{1F50D}", title: t("compliance_title"), gradient: GRADIENTS.gold }),
|
|
6198
|
+
error && /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(ResultBanner, { status: "error", message: t("compliance_import_error", { error }) }) }),
|
|
5935
6199
|
phase === "importing" && /* @__PURE__ */ jsxs34(Box33, { marginTop: SPACING.xs, flexDirection: "column", children: [
|
|
5936
|
-
/* @__PURE__ */
|
|
5937
|
-
/* @__PURE__ */
|
|
6200
|
+
/* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, children: t("compliance_import_prompt") }),
|
|
6201
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(
|
|
5938
6202
|
TextInput7,
|
|
5939
6203
|
{
|
|
5940
6204
|
defaultValue: "",
|
|
@@ -5943,20 +6207,20 @@ function ComplianceView() {
|
|
|
5943
6207
|
}
|
|
5944
6208
|
}
|
|
5945
6209
|
) }),
|
|
5946
|
-
/* @__PURE__ */
|
|
6210
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.muted, dimColor: true, children: [
|
|
5947
6211
|
"esc:",
|
|
5948
6212
|
t("hint_back")
|
|
5949
6213
|
] }) })
|
|
5950
6214
|
] }),
|
|
5951
6215
|
phase === "overview" && /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5952
|
-
!policy ? /* @__PURE__ */
|
|
5953
|
-
/* @__PURE__ */
|
|
6216
|
+
!policy ? /* @__PURE__ */ jsx37(Box33, { flexDirection: "column", children: /* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, children: t("compliance_no_policy") }) }) : /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", children: [
|
|
6217
|
+
/* @__PURE__ */ jsx37(Text35, { color: COLORS.textSecondary, bold: true, children: t("compliance_policy_by", { maintainer: policy.meta.maintainer }) }),
|
|
5954
6218
|
report ? /* @__PURE__ */ jsxs34(Box33, { flexDirection: "column", marginTop: SPACING.xs, children: [
|
|
5955
|
-
/* @__PURE__ */
|
|
5956
|
-
report.compliant ? /* @__PURE__ */
|
|
5957
|
-
] }) : /* @__PURE__ */
|
|
6219
|
+
/* @__PURE__ */ jsx37(ComplianceScore, { report }),
|
|
6220
|
+
report.compliant ? /* @__PURE__ */ jsx37(ResultBanner, { status: "success", message: t("compliance_ok") }) : /* @__PURE__ */ jsx37(ViolationList, { violations: report.violations })
|
|
6221
|
+
] }) : /* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.xs, children: /* @__PURE__ */ jsx37(Text35, { color: COLORS.muted, dimColor: true, children: t("compliance_press_r_hint") }) })
|
|
5958
6222
|
] }),
|
|
5959
|
-
/* @__PURE__ */
|
|
6223
|
+
/* @__PURE__ */ jsx37(Box33, { marginTop: SPACING.sm, flexWrap: "wrap", children: /* @__PURE__ */ jsxs34(Text35, { color: COLORS.textSecondary, children: [
|
|
5960
6224
|
"i:",
|
|
5961
6225
|
t("hint_import"),
|
|
5962
6226
|
policy && /* @__PURE__ */ jsxs34(Text35, { children: [
|
|
@@ -5979,7 +6243,7 @@ function ComplianceView() {
|
|
|
5979
6243
|
}
|
|
5980
6244
|
|
|
5981
6245
|
// src/app.tsx
|
|
5982
|
-
import { Fragment as Fragment7, jsx as
|
|
6246
|
+
import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5983
6247
|
function LicenseInitializer() {
|
|
5984
6248
|
const initLicense = useLicenseStore((s) => s.initialize);
|
|
5985
6249
|
useEffect23(() => {
|
|
@@ -5991,65 +6255,65 @@ function ViewRouter({ currentView }) {
|
|
|
5991
6255
|
const isPro = useLicenseStore((s) => s.isPro);
|
|
5992
6256
|
const isTeam = useLicenseStore((s) => s.isTeam);
|
|
5993
6257
|
if (isProView(currentView) && !isPro()) {
|
|
5994
|
-
return /* @__PURE__ */
|
|
6258
|
+
return /* @__PURE__ */ jsx38(UpgradePrompt, { viewId: currentView });
|
|
5995
6259
|
}
|
|
5996
6260
|
if (isTeamView(currentView) && !isTeam()) {
|
|
5997
|
-
return /* @__PURE__ */
|
|
6261
|
+
return /* @__PURE__ */ jsx38(UpgradePrompt, { viewId: currentView });
|
|
5998
6262
|
}
|
|
5999
6263
|
switch (currentView) {
|
|
6000
6264
|
case "dashboard":
|
|
6001
|
-
return /* @__PURE__ */
|
|
6265
|
+
return /* @__PURE__ */ jsx38(DashboardView, {});
|
|
6002
6266
|
case "installed":
|
|
6003
|
-
return /* @__PURE__ */
|
|
6267
|
+
return /* @__PURE__ */ jsx38(InstalledView, {});
|
|
6004
6268
|
case "search":
|
|
6005
|
-
return /* @__PURE__ */
|
|
6269
|
+
return /* @__PURE__ */ jsx38(SearchView, {});
|
|
6006
6270
|
case "outdated":
|
|
6007
|
-
return /* @__PURE__ */
|
|
6271
|
+
return /* @__PURE__ */ jsx38(OutdatedView, {});
|
|
6008
6272
|
case "package-info":
|
|
6009
|
-
return /* @__PURE__ */
|
|
6273
|
+
return /* @__PURE__ */ jsx38(PackageInfoView, {});
|
|
6010
6274
|
case "services":
|
|
6011
|
-
return /* @__PURE__ */
|
|
6275
|
+
return /* @__PURE__ */ jsx38(ServicesView, {});
|
|
6012
6276
|
case "doctor":
|
|
6013
|
-
return /* @__PURE__ */
|
|
6277
|
+
return /* @__PURE__ */ jsx38(DoctorView, {});
|
|
6014
6278
|
case "profiles":
|
|
6015
|
-
return /* @__PURE__ */
|
|
6279
|
+
return /* @__PURE__ */ jsx38(ProfilesView, {});
|
|
6016
6280
|
case "smart-cleanup":
|
|
6017
|
-
return /* @__PURE__ */
|
|
6281
|
+
return /* @__PURE__ */ jsx38(SmartCleanupView, {});
|
|
6018
6282
|
case "history":
|
|
6019
|
-
return /* @__PURE__ */
|
|
6283
|
+
return /* @__PURE__ */ jsx38(HistoryView, {});
|
|
6020
6284
|
case "rollback":
|
|
6021
|
-
return /* @__PURE__ */
|
|
6285
|
+
return /* @__PURE__ */ jsx38(RollbackView, {});
|
|
6022
6286
|
case "brewfile":
|
|
6023
|
-
return /* @__PURE__ */
|
|
6287
|
+
return /* @__PURE__ */ jsx38(BrewfileView, {});
|
|
6024
6288
|
case "sync":
|
|
6025
|
-
return /* @__PURE__ */
|
|
6289
|
+
return /* @__PURE__ */ jsx38(SyncView, {});
|
|
6026
6290
|
case "security-audit":
|
|
6027
|
-
return /* @__PURE__ */
|
|
6291
|
+
return /* @__PURE__ */ jsx38(SecurityAuditView, {});
|
|
6028
6292
|
case "compliance":
|
|
6029
|
-
return /* @__PURE__ */
|
|
6293
|
+
return /* @__PURE__ */ jsx38(ComplianceView, {});
|
|
6030
6294
|
case "account":
|
|
6031
|
-
return /* @__PURE__ */
|
|
6295
|
+
return /* @__PURE__ */ jsx38(AccountView, {});
|
|
6032
6296
|
}
|
|
6033
6297
|
}
|
|
6034
6298
|
function App() {
|
|
6035
6299
|
const { exit } = useApp();
|
|
6036
6300
|
const currentView = useNavigationStore((s) => s.currentView);
|
|
6037
6301
|
const isTestEnv = typeof process !== "undefined" && false;
|
|
6038
|
-
const [showWelcome, setShowWelcome] =
|
|
6302
|
+
const [showWelcome, setShowWelcome] = useState21(isTestEnv ? false : null);
|
|
6039
6303
|
useEffect23(() => {
|
|
6040
6304
|
if (isTestEnv) return;
|
|
6041
6305
|
void hasCompletedOnboarding().then((done) => setShowWelcome(!done));
|
|
6042
6306
|
}, []);
|
|
6043
6307
|
useGlobalKeyboard({ onQuit: exit });
|
|
6044
6308
|
if (showWelcome === null) {
|
|
6045
|
-
return /* @__PURE__ */
|
|
6309
|
+
return /* @__PURE__ */ jsx38(AppLayout, { children: /* @__PURE__ */ jsx38(Fragment7, {}) });
|
|
6046
6310
|
}
|
|
6047
6311
|
if (showWelcome) {
|
|
6048
|
-
return /* @__PURE__ */
|
|
6312
|
+
return /* @__PURE__ */ jsx38(AppLayout, { children: /* @__PURE__ */ jsx38(WelcomeView, { onContinue: () => setShowWelcome(false) }) });
|
|
6049
6313
|
}
|
|
6050
6314
|
return /* @__PURE__ */ jsxs35(AppLayout, { children: [
|
|
6051
|
-
/* @__PURE__ */
|
|
6052
|
-
/* @__PURE__ */
|
|
6315
|
+
/* @__PURE__ */ jsx38(LicenseInitializer, {}),
|
|
6316
|
+
/* @__PURE__ */ jsx38(ViewRouter, { currentView })
|
|
6053
6317
|
] });
|
|
6054
6318
|
}
|
|
6055
6319
|
|
|
@@ -6133,7 +6397,7 @@ async function reportError(err, context = {}) {
|
|
|
6133
6397
|
const config = await resolveConfig();
|
|
6134
6398
|
if (!config.enabled || !config.endpoint) return;
|
|
6135
6399
|
const machineId = await getMachineId();
|
|
6136
|
-
const version = true ? "
|
|
6400
|
+
const version = true ? "1.1.0" : "unknown";
|
|
6137
6401
|
await postReport(buildReport("error", err, context, machineId, version), config);
|
|
6138
6402
|
}
|
|
6139
6403
|
async function installCrashReporter() {
|
|
@@ -6142,7 +6406,7 @@ async function installCrashReporter() {
|
|
|
6142
6406
|
if (!config.enabled || !config.endpoint) return;
|
|
6143
6407
|
_installed = true;
|
|
6144
6408
|
const machineId = await getMachineId();
|
|
6145
|
-
const version = true ? "
|
|
6409
|
+
const version = true ? "1.1.0" : "unknown";
|
|
6146
6410
|
process.on("uncaughtException", (err) => {
|
|
6147
6411
|
void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
|
|
6148
6412
|
});
|
|
@@ -6153,11 +6417,11 @@ async function installCrashReporter() {
|
|
|
6153
6417
|
}
|
|
6154
6418
|
|
|
6155
6419
|
// src/index.tsx
|
|
6156
|
-
import { jsx as
|
|
6420
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
6157
6421
|
var [, , command, arg] = process.argv;
|
|
6158
6422
|
async function runCli() {
|
|
6159
6423
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
6160
|
-
process.stdout.write("
|
|
6424
|
+
process.stdout.write("1.1.0\n");
|
|
6161
6425
|
return;
|
|
6162
6426
|
}
|
|
6163
6427
|
await ensureDataDirs();
|
|
@@ -6333,14 +6597,14 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6333
6597
|
await ensureBrewBarRunning();
|
|
6334
6598
|
process.env.BREW_TUI_TUI_MODE = "1";
|
|
6335
6599
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
6336
|
-
render(/* @__PURE__ */
|
|
6600
|
+
render(/* @__PURE__ */ jsx39(App, {}));
|
|
6337
6601
|
}
|
|
6338
6602
|
async function ensureBrewBarRunning() {
|
|
6339
6603
|
if (process.platform !== "darwin") return;
|
|
6340
6604
|
await useLicenseStore.getState().initialize();
|
|
6341
6605
|
if (!useLicenseStore.getState().isPro()) return;
|
|
6342
6606
|
const { isBrewBarInstalled, installBrewBar, launchBrewBar } = await import("./brewbar-installer-GWJ76J6G.js");
|
|
6343
|
-
const { checkBrewBarVersion } = await import("./version-check-
|
|
6607
|
+
const { checkBrewBarVersion } = await import("./version-check-LVSQFXZU.js");
|
|
6344
6608
|
try {
|
|
6345
6609
|
if (!await isBrewBarInstalled()) {
|
|
6346
6610
|
console.log(t("cli_brewbarInstalling"));
|