@buoy-gg/core 1.7.8 → 2.1.2
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/lib/commonjs/Buoy.js +104 -0
- package/lib/commonjs/floatingMenu/AppHost.js +2 -2
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +18 -279
- package/lib/commonjs/floatingMenu/FloatingDevTools.js +8 -1
- package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +1 -2
- package/lib/commonjs/floatingMenu/FloatingMenu.js +4 -4
- package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +2 -2
- package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +15 -0
- package/lib/commonjs/floatingMenu/dial/DialDevTools.js +4 -4
- package/lib/commonjs/floatingMenu/floatingTools.js +268 -74
- package/lib/commonjs/index.js +24 -8
- package/lib/module/Buoy.js +100 -0
- package/lib/module/floatingMenu/AppHost.js +3 -3
- package/lib/module/floatingMenu/DevToolsSettingsModal.js +20 -281
- package/lib/module/floatingMenu/FloatingDevTools.js +8 -1
- package/lib/module/floatingMenu/FloatingDevTools.web.js +1 -2
- package/lib/module/floatingMenu/FloatingMenu.js +5 -5
- package/lib/module/floatingMenu/MinimizedToolsContext.js +3 -3
- package/lib/module/floatingMenu/autoDiscoverPresets.js +15 -0
- package/lib/module/floatingMenu/dial/DialDevTools.js +5 -5
- package/lib/module/floatingMenu/floatingTools.js +269 -75
- package/lib/module/index.js +3 -1
- package/lib/typescript/commonjs/Buoy.d.ts +79 -0
- package/lib/typescript/commonjs/Buoy.d.ts.map +1 -0
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +25 -5
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts +1 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/module/Buoy.d.ts +79 -0
- package/lib/typescript/module/Buoy.d.ts.map +1 -0
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +25 -5
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/floatingTools.d.ts +1 -1
- package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.Buoy = void 0;
|
|
7
|
+
var _license = require("@buoy-gg/license");
|
|
8
|
+
/**
|
|
9
|
+
* Buoy SDK - Main entry point for React Buoy configuration
|
|
10
|
+
*
|
|
11
|
+
* Initialize once at app startup, before rendering any components:
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { Buoy } from '@buoy-gg/core';
|
|
16
|
+
*
|
|
17
|
+
* Buoy.init({
|
|
18
|
+
* licenseKey: 'YOUR_LICENSE_KEY',
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Buoy SDK namespace
|
|
25
|
+
*
|
|
26
|
+
* Use `Buoy.init()` to configure your license key at app startup.
|
|
27
|
+
*/
|
|
28
|
+
const Buoy = exports.Buoy = {
|
|
29
|
+
/**
|
|
30
|
+
* Initialize Buoy with your license key
|
|
31
|
+
*
|
|
32
|
+
* Call this once at app startup, before rendering FloatingDevTools.
|
|
33
|
+
* Typically placed in App.tsx or index.js.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* import { Buoy } from '@buoy-gg/core';
|
|
38
|
+
*
|
|
39
|
+
* // With hardcoded key
|
|
40
|
+
* Buoy.init({
|
|
41
|
+
* licenseKey: '36063C-27282E-8E73F5-55488F-2213DF-V3',
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // With environment variable
|
|
45
|
+
* Buoy.init({
|
|
46
|
+
* licenseKey: process.env.BUOY_LICENSE_KEY!,
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
init(config) {
|
|
51
|
+
if (!config.licenseKey) {
|
|
52
|
+
console.warn("[Buoy] No license key provided to Buoy.init()");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Initialize the license manager and set the key
|
|
57
|
+
_license.LicenseManager.initialize().then(() => _license.LicenseManager.setLicenseKey(config.licenseKey)).catch(error => {
|
|
58
|
+
console.warn("[Buoy] License initialization failed:", error);
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Initialize Buoy asynchronously
|
|
63
|
+
*
|
|
64
|
+
* Use this if you need to wait for initialization to complete.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* await Buoy.initAsync({
|
|
69
|
+
* licenseKey: 'YOUR_LICENSE_KEY',
|
|
70
|
+
* });
|
|
71
|
+
* console.log('Buoy is ready!');
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
async initAsync(config) {
|
|
75
|
+
if (!config.licenseKey) {
|
|
76
|
+
console.warn("[Buoy] No license key provided to Buoy.initAsync()");
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
await _license.LicenseManager.initialize();
|
|
80
|
+
return _license.LicenseManager.setLicenseKey(config.licenseKey);
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Check if Buoy Pro is active
|
|
84
|
+
*/
|
|
85
|
+
isPro() {
|
|
86
|
+
return _license.LicenseManager.isPro();
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* Get the current license state
|
|
90
|
+
*/
|
|
91
|
+
getState() {
|
|
92
|
+
return _license.LicenseManager.getState();
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* Force device re-registration (debugging helper)
|
|
96
|
+
* Clears cached fingerprint so next init will register device again
|
|
97
|
+
*/
|
|
98
|
+
async forceReregister() {
|
|
99
|
+
await _license.LicenseManager.forceReregister();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// Also export as default for flexibility
|
|
104
|
+
var _default = exports.default = Buoy;
|
|
@@ -92,7 +92,7 @@ const AppHostProvider = ({
|
|
|
92
92
|
(0, _react.useEffect)(() => {
|
|
93
93
|
const restoreOpenApps = async () => {
|
|
94
94
|
try {
|
|
95
|
-
const saved = await
|
|
95
|
+
const saved = await _sharedUi.persistentStorage.getItem(STORAGE_KEY_OPEN_APPS);
|
|
96
96
|
if (saved) {
|
|
97
97
|
const parsed = JSON.parse(saved);
|
|
98
98
|
// Handle both old format (string[]) and new format (PersistedAppState[])
|
|
@@ -138,7 +138,7 @@ const AppHostProvider = ({
|
|
|
138
138
|
id: app.id,
|
|
139
139
|
minimized: app.minimized ?? false
|
|
140
140
|
}));
|
|
141
|
-
|
|
141
|
+
_sharedUi.persistentStorage.setItem(STORAGE_KEY_OPEN_APPS, JSON.stringify(appStates));
|
|
142
142
|
}, PERSISTENCE_DELAY);
|
|
143
143
|
return () => {
|
|
144
144
|
if (persistenceTimeoutRef.current) {
|
|
@@ -16,8 +16,6 @@ const MAX_DIAL_SLOTS = 6;
|
|
|
16
16
|
|
|
17
17
|
// Lazy load license hooks to avoid circular dependencies
|
|
18
18
|
let _useLicense = null;
|
|
19
|
-
let _useSeats = null;
|
|
20
|
-
let _useDevices = null;
|
|
21
19
|
function getUseLicense() {
|
|
22
20
|
if (!_useLicense) {
|
|
23
21
|
try {
|
|
@@ -29,28 +27,6 @@ function getUseLicense() {
|
|
|
29
27
|
}
|
|
30
28
|
return _useLicense;
|
|
31
29
|
}
|
|
32
|
-
function getUseSeats() {
|
|
33
|
-
if (!_useSeats) {
|
|
34
|
-
try {
|
|
35
|
-
const mod = require("@buoy-gg/license");
|
|
36
|
-
_useSeats = mod.useSeats;
|
|
37
|
-
} catch {
|
|
38
|
-
// License package not available
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return _useSeats;
|
|
42
|
-
}
|
|
43
|
-
function getUseDevices() {
|
|
44
|
-
if (!_useDevices) {
|
|
45
|
-
try {
|
|
46
|
-
const mod = require("@buoy-gg/license");
|
|
47
|
-
_useDevices = mod.useDevices;
|
|
48
|
-
} catch {
|
|
49
|
-
// License package not available
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return _useDevices;
|
|
53
|
-
}
|
|
54
30
|
const enforceDialLimit = dialTools => {
|
|
55
31
|
let remaining = MAX_DIAL_SLOTS;
|
|
56
32
|
const limited = {};
|
|
@@ -178,13 +154,12 @@ const DevToolsSettingsModal = ({
|
|
|
178
154
|
const [activeTabLoaded, setActiveTabLoaded] = (0, _react.useState)(false);
|
|
179
155
|
const [expandedSettings, setExpandedSettings] = (0, _react.useState)(new Set());
|
|
180
156
|
const [showLicenseModal, setShowLicenseModal] = (0, _react.useState)(false);
|
|
181
|
-
const [licenseModalForDeviceRegistration, setLicenseModalForDeviceRegistration] = (0, _react.useState)(false);
|
|
182
157
|
|
|
183
158
|
// Load persisted active tab on mount
|
|
184
159
|
(0, _react.useEffect)(() => {
|
|
185
160
|
const loadActiveTab = async () => {
|
|
186
161
|
try {
|
|
187
|
-
const savedTab = await
|
|
162
|
+
const savedTab = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.activeTab());
|
|
188
163
|
if (savedTab && ["dial", "floating", "settings", "pro"].includes(savedTab)) {
|
|
189
164
|
setActiveTab(savedTab);
|
|
190
165
|
}
|
|
@@ -201,7 +176,7 @@ const DevToolsSettingsModal = ({
|
|
|
201
176
|
(0, _react.useEffect)(() => {
|
|
202
177
|
// Only persist after initial state is loaded to avoid overwriting with default
|
|
203
178
|
if (!activeTabLoaded) return;
|
|
204
|
-
|
|
179
|
+
_sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.activeTab(), activeTab).catch(error => {
|
|
205
180
|
// Failed to save active tab - continue without persistence
|
|
206
181
|
console.warn("Failed to save settings active tab:", error);
|
|
207
182
|
});
|
|
@@ -209,22 +184,8 @@ const DevToolsSettingsModal = ({
|
|
|
209
184
|
|
|
210
185
|
// License hooks
|
|
211
186
|
const useLicenseHook = getUseLicense();
|
|
212
|
-
const useSeatsHook = getUseSeats();
|
|
213
|
-
const useDevicesHook = getUseDevices();
|
|
214
187
|
const license = useLicenseHook?.();
|
|
215
|
-
const seats = useSeatsHook?.();
|
|
216
|
-
const devicesData = useDevicesHook?.();
|
|
217
188
|
const isPro = license?.isPro ?? false;
|
|
218
|
-
|
|
219
|
-
// Devices data
|
|
220
|
-
const devices = devicesData?.devices ?? [];
|
|
221
|
-
const devicesLoading = devicesData?.isLoading ?? false;
|
|
222
|
-
const devicesError = devicesData?.error ?? null;
|
|
223
|
-
const refreshDevices = devicesData?.refreshDevices;
|
|
224
|
-
const registerDevice = devicesData?.registerDevice;
|
|
225
|
-
const deactivateDevice = devicesData?.deactivateDevice;
|
|
226
|
-
const isCurrentDeviceRegistered = devicesData?.isCurrentDeviceRegistered ?? false;
|
|
227
|
-
const [deactivatingDeviceId, setDeactivatingDeviceId] = (0, _react.useState)(null);
|
|
228
189
|
const [storageBackend, setStorageBackend] = (0, _react.useState)(null);
|
|
229
190
|
const [isClearing, setIsClearing] = (0, _react.useState)(false);
|
|
230
191
|
const [clearSuccess, setClearSuccess] = (0, _react.useState)(false);
|
|
@@ -244,7 +205,7 @@ const DevToolsSettingsModal = ({
|
|
|
244
205
|
|
|
245
206
|
const loadSettings = (0, _react.useCallback)(async () => {
|
|
246
207
|
try {
|
|
247
|
-
const savedSettings = await
|
|
208
|
+
const savedSettings = await _sharedUi.persistentStorage.getItem(STORAGE_KEY);
|
|
248
209
|
if (savedSettings) {
|
|
249
210
|
const parsed = JSON.parse(savedSettings);
|
|
250
211
|
const merged = mergeWithDefaults(defaultSettings, parsed, {
|
|
@@ -288,7 +249,7 @@ const DevToolsSettingsModal = ({
|
|
|
288
249
|
...newSettings,
|
|
289
250
|
dialTools: enforceDialLimit(newSettings.dialTools)
|
|
290
251
|
};
|
|
291
|
-
await
|
|
252
|
+
await _sharedUi.persistentStorage.setItem(STORAGE_KEY, JSON.stringify(limitedSettings));
|
|
292
253
|
setSettings(limitedSettings);
|
|
293
254
|
onSettingsChange?.(limitedSettings);
|
|
294
255
|
// Notify listeners (e.g., floating bubble) to refresh immediately
|
|
@@ -394,51 +355,6 @@ const DevToolsSettingsModal = ({
|
|
|
394
355
|
setTimeout(() => setCopySuccess(false), 2000);
|
|
395
356
|
}
|
|
396
357
|
};
|
|
397
|
-
const handleRemoveDevice = async (deviceId, deviceName, isCurrentDevice) => {
|
|
398
|
-
if (!deactivateDevice) return;
|
|
399
|
-
const message = isCurrentDevice ? "This will remove your current device. You'll need to re-register to use Pro features on this device." : `Remove "${deviceName}" from your license?`;
|
|
400
|
-
const {
|
|
401
|
-
Alert
|
|
402
|
-
} = require("react-native");
|
|
403
|
-
const doRemove = await new Promise(resolve => {
|
|
404
|
-
Alert.alert("Remove Device", message, [{
|
|
405
|
-
text: "Cancel",
|
|
406
|
-
style: "cancel",
|
|
407
|
-
onPress: () => resolve(false)
|
|
408
|
-
}, {
|
|
409
|
-
text: "Remove",
|
|
410
|
-
style: "destructive",
|
|
411
|
-
onPress: () => resolve(true)
|
|
412
|
-
}]);
|
|
413
|
-
});
|
|
414
|
-
if (!doRemove) return;
|
|
415
|
-
setDeactivatingDeviceId(deviceId);
|
|
416
|
-
try {
|
|
417
|
-
await deactivateDevice(deviceId);
|
|
418
|
-
} catch (error) {
|
|
419
|
-
console.error("Failed to remove device:", error);
|
|
420
|
-
} finally {
|
|
421
|
-
setDeactivatingDeviceId(null);
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
const handleRegisterDevice = () => {
|
|
425
|
-
// Open the license modal in device registration mode (skip license key entry)
|
|
426
|
-
setLicenseModalForDeviceRegistration(true);
|
|
427
|
-
setShowLicenseModal(true);
|
|
428
|
-
};
|
|
429
|
-
const formatDeviceDate = date => {
|
|
430
|
-
const now = new Date();
|
|
431
|
-
const diffMs = now.getTime() - date.getTime();
|
|
432
|
-
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
433
|
-
if (diffDays === 0) return "Today";
|
|
434
|
-
if (diffDays === 1) return "Yesterday";
|
|
435
|
-
if (diffDays < 7) return `${diffDays} days ago`;
|
|
436
|
-
return date.toLocaleDateString(undefined, {
|
|
437
|
-
month: "short",
|
|
438
|
-
day: "numeric",
|
|
439
|
-
year: date.getFullYear() !== now.getFullYear() ? "numeric" : undefined
|
|
440
|
-
});
|
|
441
|
-
};
|
|
442
358
|
|
|
443
359
|
// Modal is fixed to bottom sheet mode
|
|
444
360
|
const handleModeChange = (0, _react.useCallback)(_mode => {
|
|
@@ -1031,8 +947,8 @@ const DevToolsSettingsModal = ({
|
|
|
1031
947
|
})]
|
|
1032
948
|
}), activeTab === "pro" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1033
949
|
style: styles.proContainer,
|
|
1034
|
-
children: isPro ? /*#__PURE__*/(0, _jsxRuntime.
|
|
1035
|
-
children:
|
|
950
|
+
children: isPro ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
951
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1036
952
|
style: styles.proSection,
|
|
1037
953
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.SectionHeader, {
|
|
1038
954
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Icon, {
|
|
@@ -1047,173 +963,12 @@ const DevToolsSettingsModal = ({
|
|
|
1047
963
|
})]
|
|
1048
964
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1049
965
|
style: styles.proSectionContent,
|
|
1050
|
-
children: /*#__PURE__*/(0, _jsxRuntime.
|
|
1051
|
-
style: styles.
|
|
1052
|
-
children:
|
|
1053
|
-
style: styles.proStatItem,
|
|
1054
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1055
|
-
style: styles.proStatValue,
|
|
1056
|
-
children: seats?.used ?? 0
|
|
1057
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1058
|
-
style: styles.proStatLabel,
|
|
1059
|
-
children: "USED"
|
|
1060
|
-
})]
|
|
1061
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1062
|
-
style: styles.proStatDivider
|
|
1063
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1064
|
-
style: styles.proStatItem,
|
|
1065
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1066
|
-
style: styles.proStatValue,
|
|
1067
|
-
children: seats?.total ?? "∞"
|
|
1068
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1069
|
-
style: styles.proStatLabel,
|
|
1070
|
-
children: "LIMIT"
|
|
1071
|
-
})]
|
|
1072
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1073
|
-
style: styles.proStatDivider
|
|
1074
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1075
|
-
style: styles.proStatItem,
|
|
1076
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1077
|
-
style: [styles.proStatValue, (seats?.remaining ?? 0) <= 0 && styles.proStatValueDanger],
|
|
1078
|
-
children: seats?.remaining ?? "∞"
|
|
1079
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1080
|
-
style: styles.proStatLabel,
|
|
1081
|
-
children: "AVAILABLE"
|
|
1082
|
-
})]
|
|
1083
|
-
})]
|
|
966
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
967
|
+
style: styles.proActiveDescription,
|
|
968
|
+
children: "You have full access to all Buoy DevTools features."
|
|
1084
969
|
})
|
|
1085
970
|
})]
|
|
1086
|
-
})
|
|
1087
|
-
style: styles.proSection,
|
|
1088
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.SectionHeader, {
|
|
1089
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Icon, {
|
|
1090
|
-
icon: _sharedUi.Smartphone,
|
|
1091
|
-
color: _sharedUi.buoyColors.info,
|
|
1092
|
-
size: 12
|
|
1093
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Title, {
|
|
1094
|
-
children: "REGISTERED DEVICES"
|
|
1095
|
-
}), devices.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Badge, {
|
|
1096
|
-
count: devices.length,
|
|
1097
|
-
color: _sharedUi.buoyColors.info
|
|
1098
|
-
}), refreshDevices && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Actions, {
|
|
1099
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
1100
|
-
onPress: () => refreshDevices(),
|
|
1101
|
-
disabled: devicesLoading,
|
|
1102
|
-
style: {
|
|
1103
|
-
marginLeft: 8
|
|
1104
|
-
},
|
|
1105
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
|
|
1106
|
-
size: 14,
|
|
1107
|
-
color: devicesLoading ? _sharedUi.buoyColors.textMuted : _sharedUi.buoyColors.textSecondary
|
|
1108
|
-
})
|
|
1109
|
-
})
|
|
1110
|
-
})]
|
|
1111
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1112
|
-
style: styles.proSectionContent,
|
|
1113
|
-
children: [devicesLoading && devices.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1114
|
-
style: styles.proEmptyState,
|
|
1115
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1116
|
-
style: styles.proEmptyStateText,
|
|
1117
|
-
children: "Loading devices..."
|
|
1118
|
-
})
|
|
1119
|
-
}) : devicesError ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1120
|
-
style: styles.proErrorState,
|
|
1121
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
|
|
1122
|
-
size: 16,
|
|
1123
|
-
color: _sharedUi.buoyColors.error
|
|
1124
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1125
|
-
style: styles.proErrorStateText,
|
|
1126
|
-
children: devicesError
|
|
1127
|
-
})]
|
|
1128
|
-
}) : devices.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1129
|
-
style: styles.proEmptyState,
|
|
1130
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Smartphone, {
|
|
1131
|
-
size: 24,
|
|
1132
|
-
color: _sharedUi.buoyColors.textMuted
|
|
1133
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1134
|
-
style: styles.proEmptyStateText,
|
|
1135
|
-
children: "No devices registered"
|
|
1136
|
-
})]
|
|
1137
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1138
|
-
style: styles.proDevicesList,
|
|
1139
|
-
children: devices.map(device => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1140
|
-
style: [styles.proDeviceRow, device.isCurrentDevice && styles.proDeviceRowCurrent],
|
|
1141
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1142
|
-
style: styles.proDeviceIcon,
|
|
1143
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Smartphone, {
|
|
1144
|
-
size: 16,
|
|
1145
|
-
color: _sharedUi.buoyColors.text
|
|
1146
|
-
})
|
|
1147
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1148
|
-
style: styles.proDeviceInfo,
|
|
1149
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1150
|
-
style: styles.proDeviceNameRow,
|
|
1151
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1152
|
-
style: styles.proDeviceName,
|
|
1153
|
-
numberOfLines: 1,
|
|
1154
|
-
children: device.name
|
|
1155
|
-
}), device.isCurrentDevice && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
1156
|
-
style: styles.proDeviceBadge,
|
|
1157
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1158
|
-
style: styles.proDeviceBadgeText,
|
|
1159
|
-
children: "THIS DEVICE"
|
|
1160
|
-
})
|
|
1161
|
-
})]
|
|
1162
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
1163
|
-
style: styles.proDeviceDetails,
|
|
1164
|
-
children: [device.platform, device.osVersion ? ` ${device.osVersion}` : "", device.model ? ` • ${device.model}` : ""]
|
|
1165
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
1166
|
-
style: styles.proDeviceDate,
|
|
1167
|
-
children: ["Registered ", formatDeviceDate(device.registeredAt)]
|
|
1168
|
-
})]
|
|
1169
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
1170
|
-
style: styles.proDeviceRemoveBtn,
|
|
1171
|
-
onPress: () => handleRemoveDevice(device.id, device.name, device.isCurrentDevice),
|
|
1172
|
-
disabled: deactivatingDeviceId === device.id,
|
|
1173
|
-
children: deactivatingDeviceId === device.id ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.RefreshCw, {
|
|
1174
|
-
size: 14,
|
|
1175
|
-
color: _sharedUi.buoyColors.textMuted
|
|
1176
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Trash2, {
|
|
1177
|
-
size: 14,
|
|
1178
|
-
color: _sharedUi.buoyColors.error
|
|
1179
|
-
})
|
|
1180
|
-
})]
|
|
1181
|
-
}, device.id))
|
|
1182
|
-
}), !isCurrentDeviceRegistered && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
1183
|
-
style: styles.proRegisterDeviceBtn,
|
|
1184
|
-
onPress: handleRegisterDevice,
|
|
1185
|
-
disabled: devicesLoading,
|
|
1186
|
-
activeOpacity: 0.7,
|
|
1187
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Plus, {
|
|
1188
|
-
size: 14,
|
|
1189
|
-
color: _sharedUi.buoyColors.primary
|
|
1190
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1191
|
-
style: styles.proRegisterDeviceBtnText,
|
|
1192
|
-
children: "Register This Device"
|
|
1193
|
-
})]
|
|
1194
|
-
})]
|
|
1195
|
-
})]
|
|
1196
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
1197
|
-
style: styles.proSignOutBtn,
|
|
1198
|
-
onPress: () => {
|
|
1199
|
-
const {
|
|
1200
|
-
Alert
|
|
1201
|
-
} = require("react-native");
|
|
1202
|
-
Alert.alert("Sign Out of Pro?", "This will:\n\n• Remove your license key from this device\n• Deactivate this device from your license\n• Free up a seat for another device\n\nYou can sign back in anytime with your license key.", [{
|
|
1203
|
-
text: "Cancel",
|
|
1204
|
-
style: "cancel"
|
|
1205
|
-
}, {
|
|
1206
|
-
text: "Sign Out",
|
|
1207
|
-
style: "destructive",
|
|
1208
|
-
onPress: () => license?.clearLicense()
|
|
1209
|
-
}]);
|
|
1210
|
-
},
|
|
1211
|
-
activeOpacity: 0.7,
|
|
1212
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1213
|
-
style: styles.proSignOutBtnText,
|
|
1214
|
-
children: "Sign Out of Pro"
|
|
1215
|
-
})
|
|
1216
|
-
})]
|
|
971
|
+
})
|
|
1217
972
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
1218
973
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1219
974
|
style: styles.proSection,
|
|
@@ -1304,19 +1059,8 @@ const DevToolsSettingsModal = ({
|
|
|
1304
1059
|
})]
|
|
1305
1060
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.LicenseEntryModal, {
|
|
1306
1061
|
visible: showLicenseModal,
|
|
1307
|
-
onClose: () =>
|
|
1308
|
-
|
|
1309
|
-
setLicenseModalForDeviceRegistration(false);
|
|
1310
|
-
},
|
|
1311
|
-
onSuccess: () => {
|
|
1312
|
-
setShowLicenseModal(false);
|
|
1313
|
-
setLicenseModalForDeviceRegistration(false);
|
|
1314
|
-
},
|
|
1315
|
-
license: license,
|
|
1316
|
-
startAtDeviceRegistration: licenseModalForDeviceRegistration,
|
|
1317
|
-
initialExistingDevices: licenseModalForDeviceRegistration ? devices : [],
|
|
1318
|
-
initialMaxDevices: licenseModalForDeviceRegistration ? seats?.total ?? undefined : undefined,
|
|
1319
|
-
initialCurrentDeviceCount: licenseModalForDeviceRegistration ? seats?.used ?? undefined : undefined
|
|
1062
|
+
onClose: () => setShowLicenseModal(false),
|
|
1063
|
+
onSuccess: () => setShowLicenseModal(false)
|
|
1320
1064
|
})]
|
|
1321
1065
|
});
|
|
1322
1066
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
|
|
@@ -1438,7 +1182,7 @@ const useDevToolsSettings = () => {
|
|
|
1438
1182
|
const [settings, setSettings] = (0, _react.useState)(effectiveDefaults);
|
|
1439
1183
|
const loadSettings = (0, _react.useCallback)(async () => {
|
|
1440
1184
|
try {
|
|
1441
|
-
const savedSettings = await
|
|
1185
|
+
const savedSettings = await _sharedUi.persistentStorage.getItem(STORAGE_KEY);
|
|
1442
1186
|
if (savedSettings) {
|
|
1443
1187
|
const parsed = JSON.parse(savedSettings);
|
|
1444
1188
|
const merged = mergeWithDefaults(effectiveDefaults, parsed);
|
|
@@ -2235,21 +1979,16 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
2235
1979
|
fontWeight: "600",
|
|
2236
1980
|
color: _sharedUi.buoyColors.primary
|
|
2237
1981
|
},
|
|
2238
|
-
proSignOutBtn: {
|
|
2239
|
-
alignItems: "center",
|
|
2240
|
-
justifyContent: "center",
|
|
2241
|
-
paddingVertical: 12,
|
|
2242
|
-
marginTop: 8
|
|
2243
|
-
},
|
|
2244
|
-
proSignOutBtnText: {
|
|
2245
|
-
fontSize: 12,
|
|
2246
|
-
color: _sharedUi.buoyColors.textMuted
|
|
2247
|
-
},
|
|
2248
1982
|
proFreeDescription: {
|
|
2249
1983
|
fontSize: 11,
|
|
2250
1984
|
color: _sharedUi.buoyColors.textSecondary,
|
|
2251
1985
|
lineHeight: 16
|
|
2252
1986
|
},
|
|
1987
|
+
proActiveDescription: {
|
|
1988
|
+
fontSize: 11,
|
|
1989
|
+
color: _sharedUi.buoyColors.textSecondary,
|
|
1990
|
+
lineHeight: 16
|
|
1991
|
+
},
|
|
2253
1992
|
proFeaturesList: {
|
|
2254
1993
|
gap: 8
|
|
2255
1994
|
},
|
|
@@ -41,7 +41,10 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* Props for FloatingDevTools component.
|
|
44
|
-
*
|
|
44
|
+
*
|
|
45
|
+
* ZERO-CONFIG: All @buoy-gg/* tools are auto-discovered when installed.
|
|
46
|
+
* You don't need to pass anything to use network, storage, redux, etc. tools!
|
|
47
|
+
* Just install the package and it works automatically.
|
|
45
48
|
*/
|
|
46
49
|
|
|
47
50
|
/**
|
|
@@ -230,6 +233,10 @@ const FloatingDevTools = ({
|
|
|
230
233
|
// Free user in production - don't render DevTools
|
|
231
234
|
return null;
|
|
232
235
|
}
|
|
236
|
+
|
|
237
|
+
// Session blocking is handled inline by JsModal's SessionBlockedOverlay
|
|
238
|
+
// No need to replace the entire UI - tools still render, but content is blocked
|
|
239
|
+
|
|
233
240
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DefaultConfigContext.DefaultConfigProvider, {
|
|
234
241
|
defaultFloatingTools: defaultFloatingTools,
|
|
235
242
|
defaultDialTools: normalizedDialTools,
|
|
@@ -141,9 +141,8 @@ function FloatingDevTools({
|
|
|
141
141
|
visible: isSettingsOpen,
|
|
142
142
|
onClose: handleCloseSettings,
|
|
143
143
|
availableTools: availableTools,
|
|
144
|
-
onSettingsChange:
|
|
144
|
+
onSettingsChange: _newSettings => {
|
|
145
145
|
// Settings are already saved by the hook
|
|
146
|
-
console.log('Settings updated:', newSettings);
|
|
147
146
|
}
|
|
148
147
|
})]
|
|
149
148
|
});
|
|
@@ -53,7 +53,7 @@ const FloatingMenu = ({
|
|
|
53
53
|
(0, _react.useEffect)(() => {
|
|
54
54
|
const loadDialState = async () => {
|
|
55
55
|
try {
|
|
56
|
-
const savedDialOpen = await
|
|
56
|
+
const savedDialOpen = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.dial.isOpen());
|
|
57
57
|
if (savedDialOpen === "true") {
|
|
58
58
|
setShowDial(true);
|
|
59
59
|
}
|
|
@@ -70,7 +70,7 @@ const FloatingMenu = ({
|
|
|
70
70
|
(0, _react.useEffect)(() => {
|
|
71
71
|
// Only persist after initial state is loaded to avoid overwriting with default
|
|
72
72
|
if (!dialStateLoaded) return;
|
|
73
|
-
|
|
73
|
+
_sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.dial.isOpen(), showDial ? "true" : "false").catch(error => {
|
|
74
74
|
// Failed to save dial state - continue without persistence
|
|
75
75
|
console.warn("Failed to save dial state:", error);
|
|
76
76
|
});
|
|
@@ -97,7 +97,7 @@ const FloatingMenu = ({
|
|
|
97
97
|
}
|
|
98
98
|
const checkOnboarding = async () => {
|
|
99
99
|
try {
|
|
100
|
-
const hasSeenOnboarding = await
|
|
100
|
+
const hasSeenOnboarding = await _sharedUi.persistentStorage.getItem(FLOATING_MENU_ONBOARDING_KEY);
|
|
101
101
|
if (!hasSeenOnboarding) {
|
|
102
102
|
// Small delay to let the UI settle before showing tooltip
|
|
103
103
|
setTimeout(() => {
|
|
@@ -202,7 +202,7 @@ const FloatingMenu = ({
|
|
|
202
202
|
setOnboardingStep(null);
|
|
203
203
|
|
|
204
204
|
// Save to storage asynchronously in the background
|
|
205
|
-
|
|
205
|
+
_sharedUi.persistentStorage.setItem(FLOATING_MENU_ONBOARDING_KEY, "true").catch(error => {
|
|
206
206
|
// Silently fail - user already saw onboarding, just won't persist
|
|
207
207
|
console.warn("Failed to save onboarding state:", error);
|
|
208
208
|
});
|
|
@@ -115,7 +115,7 @@ function MinimizedToolsProvider({
|
|
|
115
115
|
(0, _react.useEffect)(() => {
|
|
116
116
|
const restoreMinimizedTools = async () => {
|
|
117
117
|
try {
|
|
118
|
-
const saved = await
|
|
118
|
+
const saved = await _sharedUi.persistentStorage.getItem(STORAGE_KEY);
|
|
119
119
|
if (saved) {
|
|
120
120
|
const serialized = JSON.parse(saved);
|
|
121
121
|
// Reconstruct tools with icons
|
|
@@ -145,7 +145,7 @@ function MinimizedToolsProvider({
|
|
|
145
145
|
icon,
|
|
146
146
|
...rest
|
|
147
147
|
}) => rest);
|
|
148
|
-
|
|
148
|
+
_sharedUi.persistentStorage.setItem(STORAGE_KEY, JSON.stringify(serialized));
|
|
149
149
|
}, PERSISTENCE_DELAY);
|
|
150
150
|
return () => {
|
|
151
151
|
if (persistenceTimeoutRef.current) {
|
|
@@ -194,6 +194,21 @@ function autoDiscoverPresets() {
|
|
|
194
194
|
return null;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
+
},
|
|
198
|
+
// Events Timeline
|
|
199
|
+
{
|
|
200
|
+
name: "@buoy-gg/events",
|
|
201
|
+
loader: () => {
|
|
202
|
+
try {
|
|
203
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
204
|
+
const {
|
|
205
|
+
eventsToolPreset
|
|
206
|
+
} = require("@buoy-gg/events");
|
|
207
|
+
return eventsToolPreset;
|
|
208
|
+
} catch {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
197
212
|
}];
|
|
198
213
|
|
|
199
214
|
// Attempt to load each preset
|
|
@@ -60,7 +60,7 @@ const DialDevTools = ({
|
|
|
60
60
|
(0, _react.useEffect)(() => {
|
|
61
61
|
const loadSettingsModalState = async () => {
|
|
62
62
|
try {
|
|
63
|
-
const savedModalOpen = await
|
|
63
|
+
const savedModalOpen = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.modalOpen());
|
|
64
64
|
if (savedModalOpen === "true") {
|
|
65
65
|
setIsSettingsModalOpen(true);
|
|
66
66
|
}
|
|
@@ -77,7 +77,7 @@ const DialDevTools = ({
|
|
|
77
77
|
(0, _react.useEffect)(() => {
|
|
78
78
|
// Only persist after initial state is loaded to avoid overwriting with default
|
|
79
79
|
if (!settingsModalStateLoaded) return;
|
|
80
|
-
|
|
80
|
+
_sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.modalOpen(), isSettingsModalOpen ? "true" : "false").catch(error => {
|
|
81
81
|
// Failed to save settings modal state - continue without persistence
|
|
82
82
|
console.warn("Failed to save settings modal state:", error);
|
|
83
83
|
});
|
|
@@ -112,7 +112,7 @@ const DialDevTools = ({
|
|
|
112
112
|
}
|
|
113
113
|
const checkOnboarding = async () => {
|
|
114
114
|
try {
|
|
115
|
-
const hasSeenTooltip = await
|
|
115
|
+
const hasSeenTooltip = await _sharedUi.persistentStorage.getItem(ONBOARDING_STORAGE_KEY);
|
|
116
116
|
if (!hasSeenTooltip) {
|
|
117
117
|
// Small delay to let the entrance animations play first
|
|
118
118
|
setTimeout(() => {
|
|
@@ -411,7 +411,7 @@ const DialDevTools = ({
|
|
|
411
411
|
setShowOnboardingTooltip(false);
|
|
412
412
|
|
|
413
413
|
// Save to storage asynchronously in the background
|
|
414
|
-
|
|
414
|
+
_sharedUi.persistentStorage.setItem(ONBOARDING_STORAGE_KEY, "true").catch(error => {
|
|
415
415
|
// Silently fail - user already saw onboarding, just won't persist
|
|
416
416
|
console.warn("Failed to save dial onboarding state:", error);
|
|
417
417
|
});
|