@buoy-gg/core 7.0.35 → 7.0.38
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/README.md +57 -66
- package/bin/buoy.js +71 -20
- package/lib/commonjs/Buoy.js +3 -16
- package/lib/commonjs/floatingMenu/AppHost.js +1 -1
- package/lib/commonjs/floatingMenu/AppHost.web.js +1 -1
- package/lib/commonjs/floatingMenu/AppIcon.web.js +53 -0
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +12 -5
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +14 -34
- package/lib/commonjs/floatingMenu/FloatingDevTools.js +32 -48
- package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +24 -4
- package/lib/commonjs/floatingMenu/FloatingMenu.js +1 -1
- package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +83 -4
- package/lib/commonjs/floatingMenu/MinimizedToolsStack.web.js +90 -6
- package/lib/commonjs/floatingMenu/ToolHost.js +1 -0
- package/lib/commonjs/floatingMenu/autoExternalSync.js +3 -2
- package/lib/commonjs/floatingMenu/dial/DialDevTools.js +43 -10
- package/lib/commonjs/floatingMenu/dial/DialDevTools.web.js +18 -5
- package/lib/commonjs/floatingMenu/dial/dialUsageStore.js +13 -17
- package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +37 -65
- package/lib/commonjs/floatingMenu/dial/onboardingConstants.web.js +37 -29
- package/lib/commonjs/floatingMenu/floatingTools.js +23 -889
- package/lib/commonjs/floatingMenu/floatingTools.web.js +24 -514
- package/lib/commonjs/floatingMenu/optionalRequire.js +4 -0
- package/lib/commonjs/telemetry/installPing.js +7 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/module/Buoy.js +3 -16
- package/lib/module/floatingMenu/AppHost.js +1 -1
- package/lib/module/floatingMenu/AppHost.web.js +1 -1
- package/lib/module/floatingMenu/AppIcon.web.js +47 -0
- package/lib/module/floatingMenu/DevToolsSettingsModal.js +13 -6
- package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +15 -35
- package/lib/module/floatingMenu/FloatingDevTools.js +35 -49
- package/lib/module/floatingMenu/FloatingDevTools.web.js +24 -3
- package/lib/module/floatingMenu/FloatingMenu.js +1 -1
- package/lib/module/floatingMenu/MinimizedToolsStack.js +88 -8
- package/lib/module/floatingMenu/MinimizedToolsStack.web.js +92 -8
- package/lib/module/floatingMenu/ToolHost.js +1 -0
- package/lib/module/floatingMenu/autoExternalSync.js +3 -2
- package/lib/module/floatingMenu/dial/DialDevTools.js +43 -10
- package/lib/module/floatingMenu/dial/DialDevTools.web.js +18 -5
- package/lib/module/floatingMenu/dial/dialUsageStore.js +14 -18
- package/lib/module/floatingMenu/dial/onboardingConstants.js +1 -62
- package/lib/module/floatingMenu/dial/onboardingConstants.web.js +1 -25
- package/lib/module/floatingMenu/floatingTools.js +15 -890
- package/lib/module/floatingMenu/floatingTools.web.js +1 -517
- package/lib/module/floatingMenu/optionalRequire.js +4 -0
- package/lib/module/telemetry/installPing.js +7 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/commonjs/Buoy.d.ts +14 -3
- package/lib/typescript/commonjs/Buoy.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/AppIcon.web.d.ts +14 -0
- package/lib/typescript/commonjs/floatingMenu/AppIcon.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +4 -14
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts +4 -19
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts +3 -4
- package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/dialUsageStore.d.ts +3 -15
- package/lib/typescript/commonjs/floatingMenu/dial/dialUsageStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts +1 -29
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts +1 -12
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts +6 -55
- package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts +3 -53
- package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts.map +1 -1
- package/lib/typescript/commonjs/telemetry/installPing.d.ts +8 -1
- package/lib/typescript/commonjs/telemetry/installPing.d.ts.map +1 -1
- package/lib/typescript/commonjs/version.d.ts +1 -1
- package/lib/typescript/module/Buoy.d.ts +14 -3
- package/lib/typescript/module/Buoy.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/AppIcon.web.d.ts +14 -0
- package/lib/typescript/module/floatingMenu/AppIcon.web.d.ts.map +1 -0
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +4 -14
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts +4 -19
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/ToolHost.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts +3 -4
- package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/dialUsageStore.d.ts +3 -15
- package/lib/typescript/module/floatingMenu/dial/dialUsageStore.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts +1 -29
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts +1 -12
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/floatingTools.d.ts +6 -55
- package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts +3 -53
- package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/optionalRequire.d.ts.map +1 -1
- package/lib/typescript/module/telemetry/installPing.d.ts +8 -1
- package/lib/typescript/module/telemetry/installPing.d.ts.map +1 -1
- package/lib/typescript/module/version.d.ts +1 -1
- package/package.json +6 -6
|
@@ -4,10 +4,10 @@ import { useState, useEffect, useCallback, useMemo } from "react";
|
|
|
4
4
|
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Dimensions, Platform } from "react-native";
|
|
5
5
|
import { settingsBus } from "./settingsBus.js";
|
|
6
6
|
import { useDesktopSyncStatus } from "./useDesktopSyncStatus.js";
|
|
7
|
-
import {
|
|
7
|
+
import { SentryIcon, WifiCircuitIcon, ImageOverlayIcon, RenderCountIcon, Info, Layers, ChevronRightIcon, ChevronDown, getStorageBackendType, persistentStorage, Trash2, CheckCircle2, LicenseEntryModal, BackgroundSwitcher, night, NightCard, NightRows, NightSectionLabel, NightFootnote, NightSwitch, NightButton, NightSegmented, NightBadge, NightSeparator, monoFont } from "@buoy-gg/shared-ui";
|
|
8
8
|
import { EnvIcon, StorageIcon, RoutesIcon, NetworkIcon, QueryIcon, HighlighterIcon, ReduxIcon, EventsIcon } from "@buoy-gg/floating-tools-core";
|
|
9
9
|
import { useDefaultConfig } from "./DefaultConfigContext.js";
|
|
10
|
-
import { renderAppIcon } from "./AppIcon
|
|
10
|
+
import { renderAppIcon } from "./AppIcon";
|
|
11
11
|
import { JsModal, devToolsStorageKeys } from "@buoy-gg/shared-ui";
|
|
12
12
|
import { useSafeAreaInsets } from "@buoy-gg/shared-ui";
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -374,10 +374,9 @@ export const DevToolsSettingsModal = ({
|
|
|
374
374
|
size: 18
|
|
375
375
|
});
|
|
376
376
|
case "sentry":
|
|
377
|
-
return /*#__PURE__*/_jsx(
|
|
377
|
+
return /*#__PURE__*/_jsx(SentryIcon, {
|
|
378
378
|
size: 18,
|
|
379
|
-
|
|
380
|
-
noBackground: true
|
|
379
|
+
color: "#9945FF"
|
|
381
380
|
});
|
|
382
381
|
case "storage":
|
|
383
382
|
return /*#__PURE__*/_jsx(StorageIcon, {
|
|
@@ -595,6 +594,7 @@ export const DevToolsSettingsModal = ({
|
|
|
595
594
|
contentContainerStyle: styles.scrollContainer,
|
|
596
595
|
children: [activeTab === "floating" && /*#__PURE__*/_jsx(_Fragment, {
|
|
597
596
|
children: renderSection("Floating Tools", /*#__PURE__*/_jsx(NightCard, {
|
|
597
|
+
glass: true,
|
|
598
598
|
children: /*#__PURE__*/_jsx(NightRows, {
|
|
599
599
|
children: Object.entries(settings.floatingTools).map(([key, value]) => renderToolRow(key, value, false, () => toggleFloatingTool(key)))
|
|
600
600
|
})
|
|
@@ -603,11 +603,13 @@ export const DevToolsSettingsModal = ({
|
|
|
603
603
|
}))
|
|
604
604
|
}), activeTab === "settings" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
605
605
|
children: [renderSection("Background", /*#__PURE__*/_jsx(NightCard, {
|
|
606
|
+
glass: true,
|
|
606
607
|
padded: true,
|
|
607
608
|
children: /*#__PURE__*/_jsx(BackgroundSwitcher, {
|
|
608
609
|
embedded: true
|
|
609
610
|
})
|
|
610
611
|
})), renderSection("Storage", /*#__PURE__*/_jsxs(NightCard, {
|
|
612
|
+
glass: true,
|
|
611
613
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
612
614
|
activeOpacity: 0.7,
|
|
613
615
|
onPress: () => setIsStorageExpanded(!isStorageExpanded),
|
|
@@ -688,6 +690,7 @@ export const DevToolsSettingsModal = ({
|
|
|
688
690
|
})]
|
|
689
691
|
})]
|
|
690
692
|
})), desktopSyncStatus && desktopSyncStatus.state !== "idle" && renderSection("Desktop Sync", /*#__PURE__*/_jsxs(NightCard, {
|
|
693
|
+
glass: true,
|
|
691
694
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
692
695
|
activeOpacity: 0.7,
|
|
693
696
|
onPress: () => toggleSettingExpanded("desktopSync"),
|
|
@@ -729,12 +732,14 @@ export const DevToolsSettingsModal = ({
|
|
|
729
732
|
})]
|
|
730
733
|
})]
|
|
731
734
|
})), renderSection("Modal Behavior", /*#__PURE__*/_jsx(NightCard, {
|
|
735
|
+
glass: true,
|
|
732
736
|
children: /*#__PURE__*/_jsxs(NightRows, {
|
|
733
737
|
children: [renderGlobalSettingRow("enableSharedModalDimensions", "Shared Modal Size", "Sync dimensions across all tools", "When enabled, all tool modals will share the same size and position. Resizing one modal will affect all others. When disabled, each tool remembers its own size and position independently.", "Keep OFF for the best experience. This allows you to customize each tool's modal size separately."), Platform.OS !== "web" ? renderGlobalSettingRow("expandableWindowControls", "Expand Controls", "iPad-style expandable window buttons", "When enabled, the window control buttons (minimize, toggle mode, close) start as small dots and expand into larger, easy-to-tap buttons when pressed. When disabled, buttons are directly tappable at their small size.", "Keep ON for touch devices where the small buttons are hard to press. Turn OFF if you prefer direct single-tap access.") : null]
|
|
734
738
|
})
|
|
735
739
|
}))]
|
|
736
740
|
}), activeTab === "pro" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
737
741
|
children: [renderSection("License", /*#__PURE__*/_jsx(NightCard, {
|
|
742
|
+
glass: true,
|
|
738
743
|
children: /*#__PURE__*/_jsxs(View, {
|
|
739
744
|
style: styles.settingRow,
|
|
740
745
|
children: [/*#__PURE__*/_jsx(View, {
|
|
@@ -755,6 +760,7 @@ export const DevToolsSettingsModal = ({
|
|
|
755
760
|
children: isPro ? "You have full access to all Buoy DevTools features." : licenseError ? licenseErrorIsTransport ? `Couldn't reach the license server (${licenseError}). A VPN or corporate proxy can block api.keygen.sh — turn it off and reload. Your key hasn't been rejected.` : `License check failed: ${licenseError}.` : "Upgrade to Pro to unlock all features and support development."
|
|
756
761
|
})), !isPro && /*#__PURE__*/_jsxs(_Fragment, {
|
|
757
762
|
children: [renderSection("Pro Features", /*#__PURE__*/_jsx(NightCard, {
|
|
763
|
+
glass: true,
|
|
758
764
|
children: /*#__PURE__*/_jsx(NightRows, {
|
|
759
765
|
children: ["Advanced Settings", "Priority Support"].map(feature => /*#__PURE__*/_jsxs(View, {
|
|
760
766
|
style: styles.featureRow,
|
|
@@ -790,6 +796,7 @@ export const DevToolsSettingsModal = ({
|
|
|
790
796
|
customContent: /*#__PURE__*/_jsx(View, {
|
|
791
797
|
style: styles.headerRow,
|
|
792
798
|
children: /*#__PURE__*/_jsx(NightSegmented, {
|
|
799
|
+
glass: true,
|
|
793
800
|
tabs: [{
|
|
794
801
|
key: "floating",
|
|
795
802
|
label: "Floating"
|
|
@@ -1079,7 +1086,7 @@ const styles = StyleSheet.create({
|
|
|
1079
1086
|
maxHeight: 150
|
|
1080
1087
|
},
|
|
1081
1088
|
storageKeyItem: {
|
|
1082
|
-
backgroundColor: night.color.
|
|
1089
|
+
backgroundColor: night.color.glassElevated,
|
|
1083
1090
|
borderRadius: night.radius.segment,
|
|
1084
1091
|
paddingHorizontal: 10,
|
|
1085
1092
|
paddingVertical: 7,
|
|
@@ -27,7 +27,7 @@ getToolLabel, getToolDescription,
|
|
|
27
27
|
globalSettingsConfig
|
|
28
28
|
// Types
|
|
29
29
|
} from '@buoy-gg/floating-tools-react';
|
|
30
|
-
import { QueryIcon, EnvIcon, StorageIcon, NetworkIcon, RoutesIcon, HighlighterIcon, ReduxIcon, EventsIcon, WifiIcon, ImageOverlayIcon, ZustandIcon, JotaiIcon } from '@buoy-gg/floating-tools-core';
|
|
30
|
+
import { QueryIcon, SentryIcon, EnvIcon, StorageIcon, NetworkIcon, RoutesIcon, HighlighterIcon, ReduxIcon, EventsIcon, WifiIcon, ImageOverlayIcon, ZustandIcon, JotaiIcon } from '@buoy-gg/floating-tools-core';
|
|
31
31
|
// JsModal.web + storage keys via the consumer's shared-ui web shim — the
|
|
32
32
|
// settings sheet is a real JsModal on web now, same as native. The
|
|
33
33
|
// BackgroundSwitcher is the same RN component native mounts: it renders under
|
|
@@ -61,6 +61,9 @@ const night = {
|
|
|
61
61
|
surfaceElevated: '#161618',
|
|
62
62
|
border: '#1A1A1C',
|
|
63
63
|
separator: 'rgba(255, 255, 255, 0.08)',
|
|
64
|
+
glass: 'rgba(5, 5, 5, 0.50)',
|
|
65
|
+
glassElevated: 'rgba(255, 255, 255, 0.06)',
|
|
66
|
+
glassBorder: 'rgba(255, 255, 255, 0.07)',
|
|
64
67
|
fillTertiary: 'rgba(255, 255, 255, 0.12)',
|
|
65
68
|
buttonSurface: 'rgba(8, 10, 14, 0.85)',
|
|
66
69
|
button: '#1C1C1C',
|
|
@@ -147,28 +150,6 @@ const Sparkles = ({
|
|
|
147
150
|
})]
|
|
148
151
|
});
|
|
149
152
|
|
|
150
|
-
/** Fallback for shared-ui SentryBugIcon (native sentry row icon, red). */
|
|
151
|
-
const AlertTriangle = ({
|
|
152
|
-
size = 24,
|
|
153
|
-
color = 'currentColor'
|
|
154
|
-
}) => /*#__PURE__*/_jsxs("svg", {
|
|
155
|
-
width: size,
|
|
156
|
-
height: size,
|
|
157
|
-
viewBox: "0 0 24 24",
|
|
158
|
-
fill: "none",
|
|
159
|
-
stroke: color,
|
|
160
|
-
strokeWidth: "2",
|
|
161
|
-
strokeLinecap: "round",
|
|
162
|
-
strokeLinejoin: "round",
|
|
163
|
-
children: [/*#__PURE__*/_jsx("path", {
|
|
164
|
-
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"
|
|
165
|
-
}), /*#__PURE__*/_jsx("path", {
|
|
166
|
-
d: "M12 9v4"
|
|
167
|
-
}), /*#__PURE__*/_jsx("path", {
|
|
168
|
-
d: "M12 17h.01"
|
|
169
|
-
})]
|
|
170
|
-
});
|
|
171
|
-
|
|
172
153
|
/** shared-ui Info icon (native default tool icon). */
|
|
173
154
|
const Info = ({
|
|
174
155
|
size = 24,
|
|
@@ -305,10 +286,9 @@ function ToolIcon({
|
|
|
305
286
|
size: size
|
|
306
287
|
});
|
|
307
288
|
case 'sentry':
|
|
308
|
-
|
|
309
|
-
return /*#__PURE__*/_jsx(AlertTriangle, {
|
|
289
|
+
return /*#__PURE__*/_jsx(SentryIcon, {
|
|
310
290
|
size: size,
|
|
311
|
-
color:
|
|
291
|
+
color: "#9945FF"
|
|
312
292
|
});
|
|
313
293
|
case 'storage':
|
|
314
294
|
// native passes bgColor=night surface for the BIF knock-out parts
|
|
@@ -444,11 +424,11 @@ function Footnote({
|
|
|
444
424
|
});
|
|
445
425
|
}
|
|
446
426
|
|
|
447
|
-
/** native NightCard:
|
|
427
|
+
/** native NightCard glass: 50% black, radius 14, 1px white-alpha hairline, clipped */
|
|
448
428
|
const cardStyle = {
|
|
449
|
-
backgroundColor: night.
|
|
429
|
+
backgroundColor: night.glass,
|
|
450
430
|
borderRadius: 14,
|
|
451
|
-
border: `1px solid ${night.
|
|
431
|
+
border: `1px solid ${night.glassBorder}`,
|
|
452
432
|
overflow: 'hidden'
|
|
453
433
|
};
|
|
454
434
|
|
|
@@ -793,8 +773,8 @@ export function SettingsModal({
|
|
|
793
773
|
const displayTabs = settingsTabs.filter(tab => tab.key !== 'pro');
|
|
794
774
|
|
|
795
775
|
// Segmented control rendered inside the JsModal header — native passes a
|
|
796
|
-
// NightSegmented as header.customContent the same way. Track =
|
|
797
|
-
// radius 10 / padding 3; active thumb =
|
|
776
|
+
// NightSegmented glass as header.customContent the same way. Track = glass
|
|
777
|
+
// at radius 10 / padding 3; active thumb = glassElevated at radius 8 with
|
|
798
778
|
// the accent underline glow (the Everlights All/Day tabs).
|
|
799
779
|
const tabHeader = /*#__PURE__*/_jsx("div", {
|
|
800
780
|
style: {
|
|
@@ -809,9 +789,9 @@ export function SettingsModal({
|
|
|
809
789
|
style: {
|
|
810
790
|
flex: 1,
|
|
811
791
|
display: 'flex',
|
|
812
|
-
backgroundColor: night.
|
|
792
|
+
backgroundColor: night.glass,
|
|
813
793
|
borderRadius: 10,
|
|
814
|
-
border: `1px solid ${night.
|
|
794
|
+
border: `1px solid ${night.glassBorder}`,
|
|
815
795
|
padding: 3,
|
|
816
796
|
boxSizing: 'border-box'
|
|
817
797
|
},
|
|
@@ -829,7 +809,7 @@ export function SettingsModal({
|
|
|
829
809
|
padding: '8px 0',
|
|
830
810
|
borderRadius: 8,
|
|
831
811
|
border: 'none',
|
|
832
|
-
backgroundColor: isActive ? night.
|
|
812
|
+
backgroundColor: isActive ? night.glassElevated : 'transparent',
|
|
833
813
|
color: isActive ? night.text : night.textSecondary,
|
|
834
814
|
fontSize: 13,
|
|
835
815
|
fontWeight: isActive ? 600 : 500,
|
|
@@ -1014,7 +994,7 @@ export function SettingsModal({
|
|
|
1014
994
|
},
|
|
1015
995
|
children: savedKeys.map(key => /*#__PURE__*/_jsx("div", {
|
|
1016
996
|
style: {
|
|
1017
|
-
backgroundColor: night.
|
|
997
|
+
backgroundColor: night.glassElevated,
|
|
1018
998
|
borderRadius: 8,
|
|
1019
999
|
padding: '7px 10px',
|
|
1020
1000
|
marginBottom: 4
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { FloatingToolHost } from "@buoy-gg/shared-ui";
|
|
4
|
+
import { AccountSetup } from "@buoy-gg/shared-ui";
|
|
5
|
+
import React, { useMemo, useCallback, useEffect } from "react";
|
|
4
6
|
import { View, StyleSheet } from "react-native";
|
|
5
7
|
import { AppHostProvider } from "./AppHost";
|
|
6
8
|
import { FloatingMenu } from "./FloatingMenu.js";
|
|
@@ -9,10 +11,10 @@ import { ToolOpenerBridge } from "./ToolOpenerBridge.js";
|
|
|
9
11
|
import { autoDiscoverPresets, autoDiscoverPresetsWithCustom } from "./autoDiscoverPresets.js";
|
|
10
12
|
import { sendInstallPing } from "../telemetry/installPing.js";
|
|
11
13
|
import { isTelemetryEnabled } from "../Buoy.js";
|
|
12
|
-
import { renderAppIcon } from "./AppIcon
|
|
14
|
+
import { renderAppIcon } from "./AppIcon";
|
|
13
15
|
import { DevToolsVisibilityProvider } from "./DevToolsVisibilityContext.js";
|
|
14
16
|
import { reportOptionalRequireError } from "./optionalRequire.js";
|
|
15
|
-
import { HintsProvider,
|
|
17
|
+
import { HintsProvider, normalizeEnvironment } from "@buoy-gg/shared-ui";
|
|
16
18
|
import { MinimizedToolsProvider } from "./MinimizedToolsContext.js";
|
|
17
19
|
import { validateDialConfig } from "./defaultConfig.js";
|
|
18
20
|
import { DefaultConfigProvider } from "./DefaultConfigContext.js";
|
|
@@ -120,7 +122,7 @@ export const FloatingDevTools = ({
|
|
|
120
122
|
disableHints = false,
|
|
121
123
|
defaultFloatingTools,
|
|
122
124
|
defaultDialTools,
|
|
123
|
-
requireLicense
|
|
125
|
+
requireLicense: _requireLicense,
|
|
124
126
|
licenseKey: licenseKeyProp,
|
|
125
127
|
zustandStores,
|
|
126
128
|
environment,
|
|
@@ -138,24 +140,27 @@ export const FloatingDevTools = ({
|
|
|
138
140
|
isLicensed
|
|
139
141
|
} = useProAccess();
|
|
140
142
|
|
|
141
|
-
//
|
|
143
|
+
// Account admission is mandatory; paid feature gates remain separate.
|
|
142
144
|
const {
|
|
143
145
|
licenseKey,
|
|
144
146
|
isInitialized,
|
|
145
|
-
tier
|
|
147
|
+
tier,
|
|
148
|
+
access
|
|
146
149
|
} = useLicense();
|
|
150
|
+
const configuredMatches = licenseKeyProp === undefined || licenseKeyProp.trim().toUpperCase() === (licenseKey ?? "");
|
|
151
|
+
const accountAdmitted = configuredMatches && access.status === "admitted";
|
|
147
152
|
|
|
148
153
|
// Anonymous install ping — dev-only, once a day, no project or tool data.
|
|
149
|
-
// Deliberately waits for
|
|
150
|
-
//
|
|
154
|
+
// Deliberately waits for admission to resolve so what it reports is the
|
|
155
|
+
// real outcome (the account's tier, or "locked") rather than the manager's
|
|
156
|
+
// starting state.
|
|
151
157
|
useEffect(() => {
|
|
152
|
-
if (!isInitialized) return;
|
|
158
|
+
if (!isInitialized || access.status === "initializing") return;
|
|
153
159
|
void sendInstallPing({
|
|
154
|
-
tier,
|
|
160
|
+
tier: access.status === "admitted" ? tier : "locked",
|
|
155
161
|
enabled: isTelemetryEnabled()
|
|
156
162
|
});
|
|
157
|
-
}, [isInitialized, tier]);
|
|
158
|
-
const [showLicenseModal, setShowLicenseModal] = useState(false);
|
|
163
|
+
}, [isInitialized, access.status, tier]);
|
|
159
164
|
|
|
160
165
|
// Initialize license manager on mount, and set/clear license key when prop changes.
|
|
161
166
|
// The `licenseKey` prop is the source of truth WHEN PROVIDED:
|
|
@@ -163,28 +168,12 @@ export const FloatingDevTools = ({
|
|
|
163
168
|
// - "" (blank) → EXPLICITLY clear the cached license (key was removed)
|
|
164
169
|
// - undefined → don't touch it (the app may set a key via Buoy.init())
|
|
165
170
|
useEffect(() => {
|
|
166
|
-
|
|
167
|
-
LicenseManager.initialize().then(() => LicenseManager.setLicenseKey(licenseKeyProp)).catch(() => {});
|
|
168
|
-
} else if (licenseKeyProp === "") {
|
|
169
|
-
// Explicit removal: wipe the 30-day cache so Pro actually turns off.
|
|
170
|
-
LicenseManager.initialize().then(() => LicenseManager.clearLicense()).catch(() => {});
|
|
171
|
-
} else {
|
|
172
|
-
LicenseManager.initialize();
|
|
173
|
-
}
|
|
171
|
+
void LicenseManager.configure(licenseKeyProp).catch(() => {});
|
|
174
172
|
}, [licenseKeyProp]);
|
|
175
173
|
|
|
176
|
-
// Show license modal if requireLicense is enabled and no valid license
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
if (requireLicense && isInitialized && !licenseKey) {
|
|
179
|
-
setShowLicenseModal(true);
|
|
180
|
-
} else if (licenseKey) {
|
|
181
|
-
setShowLicenseModal(false);
|
|
182
|
-
}
|
|
183
|
-
}, [requireLicense, isInitialized, licenseKey]);
|
|
184
|
-
|
|
185
174
|
// Register zustand stores once on mount if provided
|
|
186
175
|
useEffect(() => {
|
|
187
|
-
if (!zustandStores) return;
|
|
176
|
+
if (!zustandStores || access.status === "locked") return;
|
|
188
177
|
try {
|
|
189
178
|
const {
|
|
190
179
|
watchStores
|
|
@@ -193,7 +182,7 @@ export const FloatingDevTools = ({
|
|
|
193
182
|
} catch (e) {
|
|
194
183
|
reportOptionalRequireError("@buoy-gg/zustand", e);
|
|
195
184
|
}
|
|
196
|
-
}, []);
|
|
185
|
+
}, [zustandStores, access.status]);
|
|
197
186
|
|
|
198
187
|
// Normalize dial tools configuration (truncates to max 6 with warning if needed)
|
|
199
188
|
const normalizedDialTools = useMemo(() => {
|
|
@@ -450,17 +439,16 @@ export const FloatingDevTools = ({
|
|
|
450
439
|
|
|
451
440
|
// Gate: only a PAID license works outside development.
|
|
452
441
|
//
|
|
453
|
-
//
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
// here even though it validates perfectly well.
|
|
442
|
+
// A free key (and, of course, no key at all) stays dev-only. `isLicensed` is
|
|
443
|
+
// safe to gate on because `isPro` is a strict mirror of `tier === "pro"`, so
|
|
444
|
+
// a free key reports false here even though it validates perfectly well.
|
|
457
445
|
//
|
|
458
446
|
// When Business on-device login lands, this becomes the boundary that a
|
|
459
447
|
// logged-in QA/support seat crosses WITHOUT a key in the build — i.e.
|
|
460
448
|
// `isLicensed || tierSource === "session"`. Nothing else should.
|
|
461
449
|
const isDevelopment = typeof __DEV__ !== "undefined" && __DEV__;
|
|
462
450
|
if (!isDevelopment && !isLicensed) {
|
|
463
|
-
//
|
|
451
|
+
// Free or unadmitted user in production - don't render DevTools.
|
|
464
452
|
// NOTE for whoever relaxes this for the free tier: desktop sync does NOT
|
|
465
453
|
// ride on this check. It re-tests `isLicensed` itself (externalSyncGate),
|
|
466
454
|
// so opening this door does not open a broker socket. Keep it that way.
|
|
@@ -487,10 +475,16 @@ export const FloatingDevTools = ({
|
|
|
487
475
|
requiredEnvVars: requiredEnvVars,
|
|
488
476
|
customApps: syncApps
|
|
489
477
|
});
|
|
478
|
+
if (!accountAdmitted) {
|
|
479
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
480
|
+
children: [access.status === "initializing" && /*#__PURE__*/_jsxs(_Fragment, {
|
|
481
|
+
children: [ReduxAutoInstrument && /*#__PURE__*/_jsx(ReduxAutoInstrument, {}), ConsoleRoot && /*#__PURE__*/_jsx(ConsoleRoot, {}), RouteTracker && /*#__PURE__*/_jsx(RouteTracker, {}), ReactQueryTracker && /*#__PURE__*/_jsx(ReactQueryTracker, {})]
|
|
482
|
+
}), !headless && /*#__PURE__*/_jsx(AccountSetup, {})]
|
|
483
|
+
});
|
|
484
|
+
}
|
|
490
485
|
|
|
491
486
|
// Headless (sync-only): tool adapters + route tracking + desktop sync, no
|
|
492
|
-
// on-device UI.
|
|
493
|
-
// to gate. All hooks above already ran, so hook order is preserved, and
|
|
487
|
+
// on-device UI. Account admission above applies to this path too. All hooks above already ran, so hook order is preserved, and
|
|
494
488
|
// AutoExternalSync still obeys `syncEnabled` (the broker must never be
|
|
495
489
|
// contacted from a shipped build that didn't ask for it).
|
|
496
490
|
if (headless) {
|
|
@@ -506,16 +500,6 @@ export const FloatingDevTools = ({
|
|
|
506
500
|
});
|
|
507
501
|
}
|
|
508
502
|
|
|
509
|
-
// Gate: If requireLicense is enabled and no license, show only the license modal
|
|
510
|
-
if (requireLicense && isInitialized && !licenseKey) {
|
|
511
|
-
return /*#__PURE__*/_jsx(LicenseEntryModal, {
|
|
512
|
-
visible: showLicenseModal,
|
|
513
|
-
onClose: () => {} // Can't close without entering a license
|
|
514
|
-
,
|
|
515
|
-
onSuccess: () => setShowLicenseModal(false)
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
|
|
519
503
|
// Session blocking is handled inline by JsModal's SessionBlockedOverlay
|
|
520
504
|
// No need to replace the entire UI - tools still render, but content is blocked
|
|
521
505
|
|
|
@@ -538,7 +522,9 @@ export const FloatingDevTools = ({
|
|
|
538
522
|
...props,
|
|
539
523
|
apps: finalApps,
|
|
540
524
|
environment: resolvedEnvironment
|
|
541
|
-
}), props.hidden ? null : /*#__PURE__*/
|
|
525
|
+
}), props.hidden ? null : /*#__PURE__*/_jsxs(_Fragment, {
|
|
526
|
+
children: [/*#__PURE__*/_jsx(AppOverlay, {}), /*#__PURE__*/_jsx(FloatingToolHost, {})]
|
|
527
|
+
}), /*#__PURE__*/_jsx(ToolOpenerBridge, {})]
|
|
542
528
|
})
|
|
543
529
|
}), children, DebugBordersOverlay && /*#__PURE__*/_jsx(DebugBordersOverlay, {}), HighlightUpdatesOverlay && /*#__PURE__*/_jsx(HighlightUpdatesOverlay, {}), ImageOverlayOverlay && /*#__PURE__*/_jsx(ImageOverlayOverlay, {}), PerfMonitorOverlay && /*#__PURE__*/_jsx(PerfMonitorOverlay, {}), JsTopOverlay && /*#__PURE__*/_jsx(JsTopOverlay, {}), ImpersonateOverlay && /*#__PURE__*/_jsx(ImpersonateOverlay, {}), ScenariosOverlay && /*#__PURE__*/_jsx(ScenariosOverlay, {}), ReduxAutoInstrument && /*#__PURE__*/_jsx(ReduxAutoInstrument, {}), ConsoleRoot && /*#__PURE__*/_jsx(ConsoleRoot, {}), RouteTracker && /*#__PURE__*/_jsx(RouteTracker, {}), ReactQueryTracker && /*#__PURE__*/_jsx(ReactQueryTracker, {}), toolRegistry, syncEnabled && /*#__PURE__*/_jsx(AutoExternalSync, {
|
|
544
530
|
options: externalSyncOptions(externalSync),
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { FloatingToolHost } from "@buoy-gg/shared-ui/floating";
|
|
4
|
+
import { LicenseManager, useLicense } from "@buoy-gg/license";
|
|
5
|
+
import { AccountSetup } from "@buoy-gg/shared-ui";
|
|
3
6
|
/**
|
|
4
7
|
* FloatingDevTools - Unified dev tools component for React DOM Web.
|
|
5
8
|
*
|
|
@@ -84,7 +87,7 @@ function MenuLauncherIcon({
|
|
|
84
87
|
// Main Component
|
|
85
88
|
// =============================
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
function AdmittedFloatingDevTools(props) {
|
|
88
91
|
// The tool host wraps everything so dial presses can open tool components
|
|
89
92
|
// into the AppOverlay (web twin of the native AppHostProvider/AppOverlay).
|
|
90
93
|
return /*#__PURE__*/_jsx(AppHostProvider, {
|
|
@@ -369,10 +372,28 @@ function FloatingDevToolsInner({
|
|
|
369
372
|
onSettingsChange: _newSettings => {
|
|
370
373
|
// Settings are already saved by the hook
|
|
371
374
|
}
|
|
372
|
-
}), /*#__PURE__*/_jsx(AppOverlay, {})]
|
|
375
|
+
}), /*#__PURE__*/_jsx(AppOverlay, {}), /*#__PURE__*/_jsx(FloatingToolHost, {})]
|
|
373
376
|
});
|
|
374
377
|
}
|
|
375
378
|
|
|
376
379
|
// =============================
|
|
377
380
|
// Re-exports for convenience
|
|
378
|
-
// =============================
|
|
381
|
+
// =============================
|
|
382
|
+
|
|
383
|
+
export function FloatingDevTools(props) {
|
|
384
|
+
const {
|
|
385
|
+
access,
|
|
386
|
+
isPro,
|
|
387
|
+
licenseKey
|
|
388
|
+
} = useLicense();
|
|
389
|
+
useEffect(() => {
|
|
390
|
+
void LicenseManager.configure(props.licenseKey);
|
|
391
|
+
}, [props.licenseKey]);
|
|
392
|
+
const matches = props.licenseKey === undefined || props.licenseKey.trim().toUpperCase() === (licenseKey ?? "");
|
|
393
|
+
const dev = typeof __DEV__ !== "undefined" ? __DEV__ : process.env.NODE_ENV !== "production";
|
|
394
|
+
if (!dev && !isPro) return null;
|
|
395
|
+
if (!matches || access.status !== "admitted") return props.headless ? null : /*#__PURE__*/_jsx(AccountSetup, {});
|
|
396
|
+
return /*#__PURE__*/_jsx(AdmittedFloatingDevTools, {
|
|
397
|
+
...props
|
|
398
|
+
});
|
|
399
|
+
}
|
|
@@ -4,7 +4,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import { TouchableOpacity, StyleSheet, View } from "react-native";
|
|
5
5
|
import { absoluteFill } from "@buoy-gg/shared-ui";
|
|
6
6
|
import { FloatingTools, UserStatus } from "./floatingTools";
|
|
7
|
-
import { renderAppIcon } from "./AppIcon
|
|
7
|
+
import { renderAppIcon } from "./AppIcon";
|
|
8
8
|
import { DialDevTools } from "./dial/DialDevTools";
|
|
9
9
|
import { EnvironmentIndicator, persistentStorage, useHintsDisabled, devToolsStorageKeys, buoyColors } from "@buoy-gg/shared-ui";
|
|
10
10
|
import { useDevToolsSettings } from "./DevToolsSettingsModal";
|
|
@@ -1,14 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useCallback, useEffect, useRef } from "react";
|
|
4
|
-
import { Animated, TouchableOpacity, StyleSheet, Easing } from "react-native";
|
|
5
|
-
import { ExpandablePopover } from "@buoy-gg/shared-ui";
|
|
3
|
+
import React, { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
|
|
4
|
+
import { Animated, TouchableOpacity, View, Text, StyleSheet, Easing } from "react-native";
|
|
5
|
+
import { ExpandablePopover, getToolAttention, subscribeToolAttention } from "@buoy-gg/shared-ui";
|
|
6
6
|
import { useMinimizedTools } from "./MinimizedToolsContext.js";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* A hidden tool's "I need you". See `setToolAttention` in shared-ui — the tool
|
|
10
|
+
* publishes, the rail draws. Read through useSyncExternalStore so a badge set
|
|
11
|
+
* from inside a minimized sheet lands on the chip without the rail polling.
|
|
12
|
+
*/
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
function useToolAttention(toolId) {
|
|
15
|
+
return useSyncExternalStore(subscribeToolAttention, () => getToolAttention(toolId), () => getToolAttention(toolId));
|
|
16
|
+
}
|
|
17
|
+
const ATTENTION_COLORS = {
|
|
18
|
+
needsInput: "#FF8329",
|
|
19
|
+
done: "#20C997",
|
|
20
|
+
failed: "#FF3B30"
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** needsInput outranks failed outranks done — the peek shows the one that matters most. */
|
|
24
|
+
const ATTENTION_RANK = {
|
|
25
|
+
needsInput: 3,
|
|
26
|
+
failed: 2,
|
|
27
|
+
done: 1
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** The strongest attention across every minimized tool, for the folded peek. */
|
|
31
|
+
function useStrongestAttention(toolIds) {
|
|
32
|
+
const key = toolIds.join("|");
|
|
33
|
+
return useSyncExternalStore(subscribeToolAttention, () => strongest(key), () => strongest(key));
|
|
34
|
+
}
|
|
35
|
+
const strongestCache = new Map();
|
|
36
|
+
function strongest(key) {
|
|
37
|
+
let best = null;
|
|
38
|
+
for (const id of key ? key.split("|") : []) {
|
|
39
|
+
const a = getToolAttention(id);
|
|
40
|
+
if (a && (!best || ATTENTION_RANK[a.kind] > ATTENTION_RANK[best.kind])) best = a;
|
|
41
|
+
}
|
|
42
|
+
// Same value → same object, or useSyncExternalStore re-renders forever.
|
|
43
|
+
const prev = strongestCache.get(key);
|
|
44
|
+
if (prev && best && prev.kind === best.kind && prev.label === best.label) return prev;
|
|
45
|
+
if (!prev && !best) return null;
|
|
46
|
+
strongestCache.set(key, best);
|
|
47
|
+
return best;
|
|
48
|
+
}
|
|
49
|
+
|
|
8
50
|
// ============================================================================
|
|
9
51
|
// Constants
|
|
10
52
|
// ============================================================================
|
|
11
|
-
|
|
53
|
+
|
|
12
54
|
const PEEK_HEIGHT = 28;
|
|
13
55
|
const TOOLBAR_WIDTH = 44;
|
|
14
56
|
const TOOL_ITEM_SIZE = 32;
|
|
@@ -31,6 +73,7 @@ function GlitchToolButton({
|
|
|
31
73
|
onSelect,
|
|
32
74
|
index
|
|
33
75
|
}) {
|
|
76
|
+
const attention = useToolAttention(tool.id);
|
|
34
77
|
const glitchX = useRef(new Animated.Value(0)).current;
|
|
35
78
|
const glitchOpacity = useRef(new Animated.Value(1)).current;
|
|
36
79
|
const glitchScale = useRef(new Animated.Value(1)).current;
|
|
@@ -122,14 +165,14 @@ function GlitchToolButton({
|
|
|
122
165
|
clearTimeout(timeoutId);
|
|
123
166
|
};
|
|
124
167
|
}, [glitchX, glitchOpacity, glitchScale, index]);
|
|
125
|
-
return /*#__PURE__*/
|
|
168
|
+
return /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
126
169
|
onPress: () => onSelect(tool),
|
|
127
170
|
activeOpacity: 0.7,
|
|
128
171
|
style: styles.toolButton,
|
|
129
|
-
accessibilityLabel: `Restore ${tool.title}`,
|
|
172
|
+
accessibilityLabel: attention ? `${tool.title} — ${attention.label}. Restore` : `Restore ${tool.title}`,
|
|
130
173
|
accessibilityRole: "button",
|
|
131
174
|
testID: `buoy-dock-restore-${tool.id}`,
|
|
132
|
-
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
175
|
+
children: [/*#__PURE__*/_jsx(Animated.View, {
|
|
133
176
|
style: {
|
|
134
177
|
opacity: glitchOpacity,
|
|
135
178
|
transform: [{
|
|
@@ -139,7 +182,17 @@ function GlitchToolButton({
|
|
|
139
182
|
}]
|
|
140
183
|
},
|
|
141
184
|
children: tool.icon
|
|
142
|
-
})
|
|
185
|
+
}), attention ? /*#__PURE__*/_jsx(View, {
|
|
186
|
+
style: [styles.badge, {
|
|
187
|
+
backgroundColor: ATTENTION_COLORS[attention.kind]
|
|
188
|
+
}],
|
|
189
|
+
testID: `buoy-dock-badge-${tool.id}-${attention.kind}`,
|
|
190
|
+
pointerEvents: "none",
|
|
191
|
+
children: attention.kind === "needsInput" ? /*#__PURE__*/_jsx(Text, {
|
|
192
|
+
style: styles.badgeText,
|
|
193
|
+
children: "!"
|
|
194
|
+
}) : null
|
|
195
|
+
}) : null]
|
|
143
196
|
});
|
|
144
197
|
}
|
|
145
198
|
|
|
@@ -159,6 +212,7 @@ export function MinimizedToolsStack({
|
|
|
159
212
|
minimizedTools,
|
|
160
213
|
restore
|
|
161
214
|
} = useMinimizedTools();
|
|
215
|
+
const peekAttention = useStrongestAttention(minimizedTools.map(t => t.id));
|
|
162
216
|
|
|
163
217
|
// Calculate expanded height based on number of tools
|
|
164
218
|
const expandedHeight = TOOLBAR_PADDING + minimizedTools.length * TOOL_ITEM_SIZE + (minimizedTools.length - 1) * ICON_GAP + ICON_GAP + COLLAPSE_BUTTON_SIZE + 4;
|
|
@@ -182,6 +236,11 @@ export function MinimizedToolsStack({
|
|
|
182
236
|
collapsedLabel: `Show ${minimizedTools.length} minimized tools`,
|
|
183
237
|
testID: "buoy-dock-peek",
|
|
184
238
|
collapseTestID: "buoy-dock-collapse",
|
|
239
|
+
attention: peekAttention ? {
|
|
240
|
+
color: ATTENTION_COLORS[peekAttention.kind],
|
|
241
|
+
glyph: peekAttention.kind === "needsInput" ? "!" : undefined,
|
|
242
|
+
label: peekAttention.label
|
|
243
|
+
} : null,
|
|
185
244
|
children: [...minimizedTools].reverse().map((tool, index) => /*#__PURE__*/_jsx(GlitchToolButton, {
|
|
186
245
|
tool: tool,
|
|
187
246
|
onSelect: handleToolPress,
|
|
@@ -201,5 +260,26 @@ const styles = StyleSheet.create({
|
|
|
201
260
|
alignItems: "center",
|
|
202
261
|
justifyContent: "center",
|
|
203
262
|
backgroundColor: "transparent"
|
|
263
|
+
},
|
|
264
|
+
// Top-right of the chip. Needs-input carries a glyph; done/failed are a dot —
|
|
265
|
+
// the colour says which, the glyph says "act".
|
|
266
|
+
badge: {
|
|
267
|
+
position: "absolute",
|
|
268
|
+
top: 0,
|
|
269
|
+
right: 0,
|
|
270
|
+
minWidth: 12,
|
|
271
|
+
height: 12,
|
|
272
|
+
borderRadius: 6,
|
|
273
|
+
paddingHorizontal: 2,
|
|
274
|
+
alignItems: "center",
|
|
275
|
+
justifyContent: "center",
|
|
276
|
+
borderWidth: 1.5,
|
|
277
|
+
borderColor: "#0C0C0C"
|
|
278
|
+
},
|
|
279
|
+
badgeText: {
|
|
280
|
+
color: "#000",
|
|
281
|
+
fontSize: 8,
|
|
282
|
+
fontWeight: "800",
|
|
283
|
+
lineHeight: 9
|
|
204
284
|
}
|
|
205
285
|
});
|