@buoy-gg/network 7.0.41 → 7.0.43
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 +11 -85
- package/lib/commonjs/index.js +1 -332
- package/lib/commonjs/index.web.js +1 -420
- package/lib/commonjs/network/components/DataViewer.web.js +1 -879
- package/lib/commonjs/network/components/NetworkCopyScreen.web.js +1 -48
- package/lib/commonjs/network/components/NetworkCopySettingsView.js +27 -755
- package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +14 -1242
- package/lib/commonjs/network/components/NetworkDetailScreen.web.js +1 -101
- package/lib/commonjs/network/components/NetworkDetailStepper.js +1 -108
- package/lib/commonjs/network/components/NetworkDetailStepper.web.js +1 -298
- package/lib/commonjs/network/components/NetworkEventDetailView.js +15 -1130
- package/lib/commonjs/network/components/NetworkEventDetailView.web.js +15 -1484
- package/lib/commonjs/network/components/NetworkEventItemCompact.js +2 -401
- package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +2 -820
- package/lib/commonjs/network/components/NetworkFilterScreen.web.js +1 -55
- package/lib/commonjs/network/components/NetworkFilterViewV3.js +1 -442
- package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1 -1310
- package/lib/commonjs/network/components/NetworkHeaderLive.js +1 -375
- package/lib/commonjs/network/components/NetworkHeaderLive.web.js +1 -623
- package/lib/commonjs/network/components/NetworkHeaderMenu.js +1 -190
- package/lib/commonjs/network/components/NetworkListScreen.js +1 -403
- package/lib/commonjs/network/components/NetworkListScreen.web.js +1 -624
- package/lib/commonjs/network/components/NetworkModal.js +1 -786
- package/lib/commonjs/network/components/NetworkNumberPrompt.js +1 -178
- package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +1 -232
- package/lib/commonjs/network/components/NetworkOverrideEditor.js +1 -814
- package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +1 -942
- package/lib/commonjs/network/components/NetworkOverrideHeaderButton.js +1 -107
- package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +1 -133
- package/lib/commonjs/network/components/NetworkOverridesButton.js +1 -90
- package/lib/commonjs/network/components/NetworkOverridesButton.web.js +1 -143
- package/lib/commonjs/network/components/NetworkOverridesScreen.js +1 -543
- package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +1 -830
- package/lib/commonjs/network/components/NetworkSavedScreen.js +1 -226
- package/lib/commonjs/network/components/NetworkSavedScreen.web.js +1 -463
- package/lib/commonjs/network/components/NetworkUpgradeBanner.js +1 -76
- package/lib/commonjs/network/components/response-editor/Explorer.js +1 -973
- package/lib/commonjs/network/components/response-editor/Explorer.web.js +1 -1136
- package/lib/commonjs/network/components/response-editor/deleteNestedDataByPath.js +1 -56
- package/lib/commonjs/network/components/response-editor/editorContext.js +1 -33
- package/lib/commonjs/network/components/response-editor/updateNestedDataByPath.js +1 -61
- package/lib/commonjs/network/conditions/NetworkConditionsControl.js +1 -235
- package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +1 -136
- package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +1 -33
- package/lib/commonjs/network/conditions/NetworkFloatingTool.js +1 -310
- package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +1 -219
- package/lib/commonjs/network/conditions/store.js +1 -75
- package/lib/commonjs/network/conditions/wait.js +1 -43
- package/lib/commonjs/network/conditions/xhr.js +1 -135
- package/lib/commonjs/network/hooks/useLiveNetworkEvent.js +1 -62
- package/lib/commonjs/network/hooks/useNetworkBadgeCounts.js +1 -83
- package/lib/commonjs/network/hooks/useNetworkEventList.js +1 -108
- package/lib/commonjs/network/hooks/useNetworkEvents.js +1 -318
- package/lib/commonjs/network/hooks/useNetworkHasMatches.js +1 -56
- package/lib/commonjs/network/hooks/useNetworkSaved.js +1 -38
- package/lib/commonjs/network/hooks/useNetworkSelection.js +1 -53
- package/lib/commonjs/network/hooks/useOverrideRules.js +1 -36
- package/lib/commonjs/network/hooks/useTickEveryMinute.js +1 -21
- package/lib/commonjs/network/overrides/applyToFetch.js +1 -80
- package/lib/commonjs/network/overrides/applyToXhr.js +2 -510
- package/lib/commonjs/network/overrides/engine.js +1 -93
- package/lib/commonjs/network/overrides/matchRule.js +1 -87
- package/lib/commonjs/network/overrides/overriddenRows.js +1 -37
- package/lib/commonjs/network/overrides/overrideRulesStore.js +1 -550
- package/lib/commonjs/network/overrides/presets.js +1 -70
- package/lib/commonjs/network/overrides/resolveOverride.js +1 -158
- package/lib/commonjs/network/overrides/types.js +1 -90
- package/lib/commonjs/network/sync/networkBodyResolver.js +1 -39
- package/lib/commonjs/network/sync/networkSyncAdapter.js +1 -882
- package/lib/commonjs/network/sync/overrideHonesty.release.test.js +1 -36
- package/lib/commonjs/network/types/index.js +1 -5
- package/lib/commonjs/network/utils/extractOperationName.js +1 -80
- package/lib/commonjs/network/utils/filterNetworkEvents.js +1 -96
- package/lib/commonjs/network/utils/formatGraphQLVariables.js +1 -219
- package/lib/commonjs/network/utils/formatting.js +1 -30
- package/lib/commonjs/network/utils/generateCurl.js +2 -71
- package/lib/commonjs/network/utils/generateNetworkCopyText.js +37 -166
- package/lib/commonjs/network/utils/httpCompletion.js +1 -37
- package/lib/commonjs/network/utils/networkEventStore.js +1 -411
- package/lib/commonjs/network/utils/networkListener.js +4 -1352
- package/lib/commonjs/network/utils/networkSavedStore.js +3 -577
- package/lib/commonjs/network/utils/networkSelectionStore.js +1 -193
- package/lib/commonjs/network/utils/realNow.js +1 -0
- package/lib/commonjs/network/utils/requestId.js +1 -16
- package/lib/commonjs/network/utils/resolveRequestUrl.js +1 -15
- package/lib/commonjs/network/utils/selectSavedEvents.js +1 -39
- package/lib/commonjs/network/utils/startNetworkCapture.js +1 -24
- package/lib/commonjs/network/utils/withPinnedFirst.js +1 -32
- package/lib/commonjs/preset.js +1 -93
- package/lib/module/index.js +1 -104
- package/lib/module/index.web.js +1 -82
- package/lib/module/network/components/DataViewer.web.js +1 -875
- package/lib/module/network/components/NetworkCopyScreen.web.js +1 -44
- package/lib/module/network/components/NetworkCopySettingsView.js +27 -750
- package/lib/module/network/components/NetworkCopySettingsView.web.js +14 -1237
- package/lib/module/network/components/NetworkDetailScreen.web.js +1 -97
- package/lib/module/network/components/NetworkDetailStepper.js +1 -104
- package/lib/module/network/components/NetworkDetailStepper.web.js +1 -296
- package/lib/module/network/components/NetworkEventDetailView.js +15 -1129
- package/lib/module/network/components/NetworkEventDetailView.web.js +15 -1482
- package/lib/module/network/components/NetworkEventItemCompact.js +2 -398
- package/lib/module/network/components/NetworkEventItemCompact.web.js +2 -818
- package/lib/module/network/components/NetworkFilterScreen.web.js +1 -51
- package/lib/module/network/components/NetworkFilterViewV3.js +1 -438
- package/lib/module/network/components/NetworkFilterViewV3.web.js +1 -1306
- package/lib/module/network/components/NetworkHeaderLive.js +1 -366
- package/lib/module/network/components/NetworkHeaderLive.web.js +1 -617
- package/lib/module/network/components/NetworkHeaderMenu.js +1 -184
- package/lib/module/network/components/NetworkListScreen.js +1 -399
- package/lib/module/network/components/NetworkListScreen.web.js +1 -622
- package/lib/module/network/components/NetworkModal.js +1 -781
- package/lib/module/network/components/NetworkNumberPrompt.js +1 -174
- package/lib/module/network/components/NetworkNumberPrompt.web.js +1 -230
- package/lib/module/network/components/NetworkOverrideEditor.js +1 -811
- package/lib/module/network/components/NetworkOverrideEditor.web.js +1 -939
- package/lib/module/network/components/NetworkOverrideHeaderButton.js +1 -104
- package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +1 -131
- package/lib/module/network/components/NetworkOverridesButton.js +1 -87
- package/lib/module/network/components/NetworkOverridesButton.web.js +1 -141
- package/lib/module/network/components/NetworkOverridesScreen.js +1 -539
- package/lib/module/network/components/NetworkOverridesScreen.web.js +1 -826
- package/lib/module/network/components/NetworkSavedScreen.js +1 -222
- package/lib/module/network/components/NetworkSavedScreen.web.js +1 -461
- package/lib/module/network/components/NetworkUpgradeBanner.js +1 -72
- package/lib/module/network/components/response-editor/Explorer.js +1 -972
- package/lib/module/network/components/response-editor/Explorer.web.js +1 -1133
- package/lib/module/network/components/response-editor/deleteNestedDataByPath.js +1 -51
- package/lib/module/network/components/response-editor/editorContext.js +1 -29
- package/lib/module/network/components/response-editor/updateNestedDataByPath.js +1 -56
- package/lib/module/network/conditions/NetworkConditionsControl.js +1 -231
- package/lib/module/network/conditions/NetworkConditionsControl.test.js +1 -135
- package/lib/module/network/conditions/NetworkConditionsIcon.js +1 -29
- package/lib/module/network/conditions/NetworkFloatingTool.js +1 -304
- package/lib/module/network/conditions/NetworkFloatingTool.test.js +1 -218
- package/lib/module/network/conditions/store.js +1 -65
- package/lib/module/network/conditions/wait.js +1 -38
- package/lib/module/network/conditions/xhr.js +1 -131
- package/lib/module/network/hooks/useLiveNetworkEvent.js +1 -58
- package/lib/module/network/hooks/useNetworkBadgeCounts.js +1 -79
- package/lib/module/network/hooks/useNetworkEventList.js +1 -104
- package/lib/module/network/hooks/useNetworkEvents.js +1 -314
- package/lib/module/network/hooks/useNetworkHasMatches.js +1 -52
- package/lib/module/network/hooks/useNetworkSaved.js +1 -34
- package/lib/module/network/hooks/useNetworkSelection.js +1 -46
- package/lib/module/network/hooks/useOverrideRules.js +1 -32
- package/lib/module/network/hooks/useTickEveryMinute.js +1 -11
- package/lib/module/network/overrides/applyToFetch.js +1 -72
- package/lib/module/network/overrides/applyToXhr.js +2 -502
- package/lib/module/network/overrides/engine.js +1 -85
- package/lib/module/network/overrides/matchRule.js +1 -81
- package/lib/module/network/overrides/overriddenRows.js +1 -33
- package/lib/module/network/overrides/overrideRulesStore.js +1 -547
- package/lib/module/network/overrides/presets.js +1 -65
- package/lib/module/network/overrides/resolveOverride.js +1 -152
- package/lib/module/network/overrides/types.js +1 -86
- package/lib/module/network/sync/networkBodyResolver.js +1 -34
- package/lib/module/network/sync/networkSyncAdapter.js +1 -880
- package/lib/module/network/sync/overrideHonesty.release.test.js +1 -35
- package/lib/module/network/types/index.js +1 -3
- package/lib/module/network/utils/extractOperationName.js +1 -76
- package/lib/module/network/utils/filterNetworkEvents.js +1 -92
- package/lib/module/network/utils/formatGraphQLVariables.js +1 -213
- package/lib/module/network/utils/formatting.js +1 -9
- package/lib/module/network/utils/generateCurl.js +2 -67
- package/lib/module/network/utils/generateNetworkCopyText.js +37 -162
- package/lib/module/network/utils/httpCompletion.js +1 -32
- package/lib/module/network/utils/networkEventStore.js +1 -409
- package/lib/module/network/utils/networkListener.js +4 -1341
- package/lib/module/network/utils/networkSavedStore.js +3 -572
- package/lib/module/network/utils/networkSelectionStore.js +1 -188
- package/lib/module/network/utils/realNow.js +1 -0
- package/lib/module/network/utils/requestId.js +1 -12
- package/lib/module/network/utils/resolveRequestUrl.js +1 -11
- package/lib/module/network/utils/selectSavedEvents.js +1 -35
- package/lib/module/network/utils/startNetworkCapture.js +1 -21
- package/lib/module/network/utils/withPinnedFirst.js +1 -28
- package/lib/module/preset.js +1 -91
- package/lib/typescript/network/overrides/engine.d.ts +1 -1
- package/lib/typescript/network/overrides/matchRule.d.ts +1 -1
- package/lib/typescript/network/overrides/resolveOverride.d.ts +2 -2
- package/lib/typescript/network/overrides/types.d.ts +9 -0
- package/lib/typescript/network/utils/networkListener.d.ts +11 -0
- package/lib/typescript/network/utils/realNow.d.ts +18 -0
- package/lib/web/index.mjs +73 -74
- package/package.json +3 -6
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/index.web.d.ts.map +0 -1
- package/lib/typescript/network/components/DataViewer.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkCopySettingsView.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkFilterViewV3.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkListScreen.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkModal.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkNumberPrompt.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverrideEditor.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverridesButton.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkSavedScreen.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +0 -1
- package/lib/typescript/network/components/NetworkUpgradeBanner.d.ts.map +0 -1
- package/lib/typescript/network/components/response-editor/Explorer.d.ts.map +0 -1
- package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +0 -1
- package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts.map +0 -1
- package/lib/typescript/network/components/response-editor/editorContext.d.ts.map +0 -1
- package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts.map +0 -1
- package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts.map +0 -1
- package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts.map +0 -1
- package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts.map +0 -1
- package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts.map +0 -1
- package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts.map +0 -1
- package/lib/typescript/network/conditions/store.d.ts.map +0 -1
- package/lib/typescript/network/conditions/wait.d.ts.map +0 -1
- package/lib/typescript/network/conditions/xhr.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useLiveNetworkEvent.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkBadgeCounts.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkEvents.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkHasMatches.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkSaved.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useNetworkSelection.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useOverrideRules.d.ts.map +0 -1
- package/lib/typescript/network/hooks/useTickEveryMinute.d.ts.map +0 -1
- package/lib/typescript/network/overrides/applyToFetch.d.ts.map +0 -1
- package/lib/typescript/network/overrides/applyToXhr.d.ts.map +0 -1
- package/lib/typescript/network/overrides/engine.d.ts.map +0 -1
- package/lib/typescript/network/overrides/matchRule.d.ts.map +0 -1
- package/lib/typescript/network/overrides/overriddenRows.d.ts.map +0 -1
- package/lib/typescript/network/overrides/overrideRulesStore.d.ts.map +0 -1
- package/lib/typescript/network/overrides/presets.d.ts.map +0 -1
- package/lib/typescript/network/overrides/resolveOverride.d.ts.map +0 -1
- package/lib/typescript/network/overrides/types.d.ts.map +0 -1
- package/lib/typescript/network/sync/networkBodyResolver.d.ts.map +0 -1
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/network/sync/overrideHonesty.release.test.d.ts.map +0 -1
- package/lib/typescript/network/types/index.d.ts.map +0 -1
- package/lib/typescript/network/utils/extractOperationName.d.ts.map +0 -1
- package/lib/typescript/network/utils/filterNetworkEvents.d.ts.map +0 -1
- package/lib/typescript/network/utils/formatGraphQLVariables.d.ts.map +0 -1
- package/lib/typescript/network/utils/formatting.d.ts.map +0 -1
- package/lib/typescript/network/utils/generateCurl.d.ts.map +0 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +0 -1
- package/lib/typescript/network/utils/httpCompletion.d.ts.map +0 -1
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +0 -1
- package/lib/typescript/network/utils/networkListener.d.ts.map +0 -1
- package/lib/typescript/network/utils/networkSavedStore.d.ts.map +0 -1
- package/lib/typescript/network/utils/networkSelectionStore.d.ts.map +0 -1
- package/lib/typescript/network/utils/requestId.d.ts.map +0 -1
- package/lib/typescript/network/utils/resolveRequestUrl.d.ts.map +0 -1
- package/lib/typescript/network/utils/selectSavedEvents.d.ts.map +0 -1
- package/lib/typescript/network/utils/startNetworkCapture.d.ts.map +0 -1
- package/lib/typescript/network/utils/withPinnedFirst.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
|
@@ -1,539 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
4
|
-
import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
5
|
-
import { AlertCircle, AlertTriangle, DevToolsCard, EmptyState, MethodBadge, Plus, Trash2, macOSColors, useLimit, monoFont } from "@buoy-gg/shared-ui";
|
|
6
|
-
import { useOverrideRules } from "../hooks/useOverrideRules";
|
|
7
|
-
import { NetworkOverrideEditor } from "./NetworkOverrideEditor";
|
|
8
|
-
import { overrideRulesStore } from "../overrides/overrideRulesStore";
|
|
9
|
-
import { MAX_RULES } from "../overrides/types";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The rule manager: what's armed, and how to stop all of it.
|
|
13
|
-
*
|
|
14
|
-
* One bar across the top is both the warning and the switch. It used to be two
|
|
15
|
-
* things — an ON/OFF pill beside a title, and a separate banner saying the same
|
|
16
|
-
* thing in different words — which left the pill reading as though it applied
|
|
17
|
-
* to the selected rule. A state pill is ambiguous; a verb button isn't.
|
|
18
|
-
*/
|
|
19
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
-
function blankDraft() {
|
|
21
|
-
return {
|
|
22
|
-
enabled: true,
|
|
23
|
-
urlPattern: "",
|
|
24
|
-
kind: "respond",
|
|
25
|
-
status: 500,
|
|
26
|
-
body: "",
|
|
27
|
-
times: null
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function toDraft(rule) {
|
|
31
|
-
const {
|
|
32
|
-
id: _id,
|
|
33
|
-
hits: _hits,
|
|
34
|
-
seen: _seen,
|
|
35
|
-
createdAt: _createdAt,
|
|
36
|
-
...draft
|
|
37
|
-
} = rule;
|
|
38
|
-
return draft;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Where the rule applies — PATH only, not the whole URL.
|
|
43
|
-
*
|
|
44
|
-
* The host is the same for every rule in a typical app, so showing it pushes
|
|
45
|
-
* the part that differs off the end of the line. Same reasoning as the request
|
|
46
|
-
* row's `displayUrl`.
|
|
47
|
-
*/
|
|
48
|
-
function patternPath(rule) {
|
|
49
|
-
const path = rule.urlPattern;
|
|
50
|
-
const schemeEnd = path.indexOf("://");
|
|
51
|
-
if (schemeEnd === -1) return path;
|
|
52
|
-
const slash = path.indexOf("/", schemeEnd + 3);
|
|
53
|
-
return slash === -1 ? path.slice(schemeEnd + 3) : path.slice(slash);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Delay and lifetime, in the editor's own words. Empty for a plain rule. */
|
|
57
|
-
function extrasLine(rule) {
|
|
58
|
-
const parts = [];
|
|
59
|
-
if (rule.delayMs) parts.push(`${rule.delayMs / 1000}s delay`);
|
|
60
|
-
if (rule.alternate) parts.push("every other");else if (rule.times === 1) parts.push("once");else if (typeof rule.times === "number") parts.push(`${rule.times}×`);
|
|
61
|
-
return parts.join(" · ");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** The outcome's color, on the request list's status scale — a forced 500
|
|
65
|
-
* should look exactly like a real one. */
|
|
66
|
-
function ruleAccent(rule) {
|
|
67
|
-
if (rule.kind === "fail") return macOSColors.semantic.error;
|
|
68
|
-
if (rule.kind === "delay") return macOSColors.semantic.info;
|
|
69
|
-
const status = rule.status ?? 200;
|
|
70
|
-
if (status >= 200 && status < 300) return macOSColors.semantic.success;
|
|
71
|
-
if (status >= 300 && status < 400) return macOSColors.semantic.info;
|
|
72
|
-
return macOSColors.semantic.error;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* One rule, in the request row's visual language — the same card, method badge,
|
|
77
|
-
* monospace path and status colors as `NetworkEventItemCompact`, so a rule
|
|
78
|
-
* reads as "the request it will produce". What's different is what a rule
|
|
79
|
-
* needs: a trash instead of the type chip and chevron, and the outcome color
|
|
80
|
-
* only floods the left edge while the rule is live. There's no per-rule
|
|
81
|
-
* on/off — a rule you don't want anymore gets deleted, and pausing everything
|
|
82
|
-
* is the master bar's job.
|
|
83
|
-
*/
|
|
84
|
-
function RuleRow({
|
|
85
|
-
rule,
|
|
86
|
-
spent,
|
|
87
|
-
onEdit,
|
|
88
|
-
onDelete
|
|
89
|
-
}) {
|
|
90
|
-
const live = rule.enabled && !spent;
|
|
91
|
-
const accent = ruleAccent(rule);
|
|
92
|
-
const extras = extrasLine(rule);
|
|
93
|
-
const method = rule.methods?.length ? rule.methods.join("/") : "ANY";
|
|
94
|
-
return /*#__PURE__*/_jsxs(DevToolsCard, {
|
|
95
|
-
onPress: onEdit,
|
|
96
|
-
style: styles.cardWrapper,
|
|
97
|
-
contentStyle: [styles.card, {
|
|
98
|
-
borderLeftColor: live ? accent : "transparent"
|
|
99
|
-
}],
|
|
100
|
-
children: [/*#__PURE__*/_jsx(MethodBadge, {
|
|
101
|
-
method: method,
|
|
102
|
-
size: "small"
|
|
103
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
104
|
-
style: styles.cardMiddle,
|
|
105
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
106
|
-
style: [styles.urlText, !live && styles.urlTextOff],
|
|
107
|
-
numberOfLines: 2,
|
|
108
|
-
children: patternPath(rule)
|
|
109
|
-
}), extras ? /*#__PURE__*/_jsx(Text, {
|
|
110
|
-
style: styles.extrasText,
|
|
111
|
-
children: extras
|
|
112
|
-
}) : null]
|
|
113
|
-
}), rule.hits > 0 ? /*#__PURE__*/_jsx(Text, {
|
|
114
|
-
style: styles.rowHits,
|
|
115
|
-
children: rule.hits
|
|
116
|
-
}) : null, rule.kind === "fail" ? /*#__PURE__*/_jsxs(View, {
|
|
117
|
-
style: styles.failBadge,
|
|
118
|
-
children: [/*#__PURE__*/_jsx(AlertCircle, {
|
|
119
|
-
size: 10,
|
|
120
|
-
color: macOSColors.semantic.error
|
|
121
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
122
|
-
style: styles.failText,
|
|
123
|
-
children: rule.failKind === "timeout" ? "TIMEOUT" : "OFFLINE"
|
|
124
|
-
})]
|
|
125
|
-
}) : /*#__PURE__*/_jsx(Text, {
|
|
126
|
-
style: [styles.statusText, {
|
|
127
|
-
color: accent
|
|
128
|
-
}],
|
|
129
|
-
children: rule.kind === "delay" ? "PASS" : String(rule.status ?? 200)
|
|
130
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
131
|
-
onPress: onDelete,
|
|
132
|
-
"sentry-label": "ignore delete override rule",
|
|
133
|
-
testID: "buoy-network-rule-delete",
|
|
134
|
-
accessibilityRole: "button",
|
|
135
|
-
accessibilityLabel: "Delete rule",
|
|
136
|
-
hitSlop: {
|
|
137
|
-
top: 8,
|
|
138
|
-
bottom: 8,
|
|
139
|
-
left: 4,
|
|
140
|
-
right: 4
|
|
141
|
-
},
|
|
142
|
-
style: styles.rowDelete,
|
|
143
|
-
children: /*#__PURE__*/_jsx(Trash2, {
|
|
144
|
-
size: 13,
|
|
145
|
-
color: macOSColors.text.muted
|
|
146
|
-
})
|
|
147
|
-
})]
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Stable-router gate.
|
|
152
|
-
*
|
|
153
|
-
* The screens in `NetworkModal` are rendered as permanent siblings, and the
|
|
154
|
-
* convention there is that a HIDDEN screen must not subscribe to anything.
|
|
155
|
-
* Splitting the body out is how this one honours that: `useOverrideRules`
|
|
156
|
-
* subscribes to a store that ticks while rules are firing, and a hidden screen
|
|
157
|
-
* re-rendering for that would be pure waste. (The header's overrides button is
|
|
158
|
-
* a deliberate exception — it's always visible and its whole job is to react.)
|
|
159
|
-
*/
|
|
160
|
-
export function NetworkOverridesScreen(props) {
|
|
161
|
-
if (!props.visible) return null;
|
|
162
|
-
return /*#__PURE__*/_jsx(OverridesBody, {
|
|
163
|
-
...props
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
function OverridesBody({
|
|
167
|
-
isPro,
|
|
168
|
-
onUpgradePress,
|
|
169
|
-
pendingDraft,
|
|
170
|
-
onPendingConsumed,
|
|
171
|
-
backHandlerRef,
|
|
172
|
-
applySafeAreaInset
|
|
173
|
-
}) {
|
|
174
|
-
// `isPro` stays a prop so callers can force the unlimited view.
|
|
175
|
-
const tierRuleLimit = useLimit("network.overrideRules");
|
|
176
|
-
const ruleLimit = isPro ? MAX_RULES : tierRuleLimit;
|
|
177
|
-
const {
|
|
178
|
-
enabled,
|
|
179
|
-
autoPaused,
|
|
180
|
-
rules,
|
|
181
|
-
activeCount,
|
|
182
|
-
setEnabled,
|
|
183
|
-
upsertRule,
|
|
184
|
-
setRuleEnabled,
|
|
185
|
-
removeRule,
|
|
186
|
-
isRuleSpent
|
|
187
|
-
} = useOverrideRules();
|
|
188
|
-
const [editing, setEditing] = useState(null);
|
|
189
|
-
|
|
190
|
-
// Reaching this screen proves the app renders, so the launch-safety streak
|
|
191
|
-
// has nothing to guard against — see `noteHealthyLaunch`.
|
|
192
|
-
useEffect(() => {
|
|
193
|
-
overrideRulesStore.noteHealthyLaunch();
|
|
194
|
-
}, []);
|
|
195
|
-
|
|
196
|
-
// Back while editing means "back to the rule list", not "leave overrides" —
|
|
197
|
-
// see the prop's comment. Cleared on unmount so a hidden screen can't
|
|
198
|
-
// swallow back presses.
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
if (!backHandlerRef) return;
|
|
201
|
-
backHandlerRef.current = editing ? () => {
|
|
202
|
-
setEditing(null);
|
|
203
|
-
return true;
|
|
204
|
-
} : null;
|
|
205
|
-
return () => {
|
|
206
|
-
backHandlerRef.current = null;
|
|
207
|
-
};
|
|
208
|
-
}, [backHandlerRef, editing]);
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Open a rule for editing, pulling its body over if this surface doesn't have
|
|
212
|
-
* it.
|
|
213
|
-
*
|
|
214
|
-
* On the device that's already the case and the fetch resolves synchronously.
|
|
215
|
-
* On the dashboard a large body is left out of the snapshot on purpose (see
|
|
216
|
-
* `stripLargeRuleBodies`), so it arrives a moment after the editor does — the
|
|
217
|
-
* `id` re-check keeps a slow reply from landing in a rule you've since moved
|
|
218
|
-
* on from.
|
|
219
|
-
*/
|
|
220
|
-
const hydrateBody = useCallback(id => {
|
|
221
|
-
void overrideRulesStore.fetchRuleBody(id).then(body => {
|
|
222
|
-
if (body == null) return;
|
|
223
|
-
setEditing(current => current?.id === id ? {
|
|
224
|
-
...current,
|
|
225
|
-
draft: {
|
|
226
|
-
...current.draft,
|
|
227
|
-
body,
|
|
228
|
-
bodyOmitted: undefined
|
|
229
|
-
}
|
|
230
|
-
} : current);
|
|
231
|
-
});
|
|
232
|
-
}, []);
|
|
233
|
-
useEffect(() => {
|
|
234
|
-
if (!pendingDraft) return;
|
|
235
|
-
const {
|
|
236
|
-
id,
|
|
237
|
-
...draft
|
|
238
|
-
} = pendingDraft;
|
|
239
|
-
setEditing({
|
|
240
|
-
id,
|
|
241
|
-
draft
|
|
242
|
-
});
|
|
243
|
-
// Same reason as `openRule`: the detail page's Override button hands over an
|
|
244
|
-
// existing rule, and on the dashboard that rule's body may not be here yet.
|
|
245
|
-
if (id && draft.bodyOmitted) hydrateBody(id);
|
|
246
|
-
onPendingConsumed?.();
|
|
247
|
-
}, [pendingDraft, onPendingConsumed, hydrateBody]);
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Leave the editor when the rule it's editing stops existing.
|
|
251
|
-
*
|
|
252
|
-
* Rules can be cleared from somewhere else — the dashboard, an MCP agent —
|
|
253
|
-
* while this editor is open. Without this, Save would upsert the old id and
|
|
254
|
-
* quietly RESURRECT a rule someone had just deleted. Only guards existing
|
|
255
|
-
* rules; a draft with no id yet is a new rule and has nothing to lose.
|
|
256
|
-
*/
|
|
257
|
-
useEffect(() => {
|
|
258
|
-
if (!editing?.id) return;
|
|
259
|
-
if (rules.some(rule => rule.id === editing.id)) return;
|
|
260
|
-
setEditing(null);
|
|
261
|
-
}, [editing?.id, rules]);
|
|
262
|
-
const openRule = rule => {
|
|
263
|
-
setEditing({
|
|
264
|
-
id: rule.id,
|
|
265
|
-
draft: toDraft(rule)
|
|
266
|
-
});
|
|
267
|
-
if (rule.bodyOmitted) hydrateBody(rule.id);
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* On the free tier a new rule REPLACES the live one rather than being refused.
|
|
272
|
-
*
|
|
273
|
-
* The old behaviour put an upgrade modal in the action path: you tapped a
|
|
274
|
-
* thing and got a sales pitch instead of the thing. Nobody buys from a modal
|
|
275
|
-
* that just cancelled their action, and it hid the feature behind a wall
|
|
276
|
-
* instead of letting you feel its shape. "One override at a time" is a shape
|
|
277
|
-
* a developer understands.
|
|
278
|
-
*/
|
|
279
|
-
const enforceRuleLimit = keepId => {
|
|
280
|
-
// Only trims when the tier is actually over its cap, so Pro (whose limit
|
|
281
|
-
// is the hard MAX_RULES ceiling) is never touched.
|
|
282
|
-
const active = rules.filter(rule => rule.enabled && !isRuleSpent(rule));
|
|
283
|
-
if (active.length <= ruleLimit) return;
|
|
284
|
-
rules.filter(rule => rule.enabled && !isRuleSpent(rule) && rule.id !== keepId).forEach(rule => setRuleEnabled(rule.id, false));
|
|
285
|
-
};
|
|
286
|
-
const handleSave = () => {
|
|
287
|
-
if (!editing) return;
|
|
288
|
-
// Saving always arms the rule. With no per-rule toggle, this is the ONLY
|
|
289
|
-
// way back on for a rule the free tier disabled or that used itself up —
|
|
290
|
-
// and nobody edits a rule they want to stay inert.
|
|
291
|
-
const draft = {
|
|
292
|
-
...editing.draft,
|
|
293
|
-
enabled: true,
|
|
294
|
-
urlPattern: editing.draft.urlPattern.trim()
|
|
295
|
-
};
|
|
296
|
-
if (!draft.urlPattern) return;
|
|
297
|
-
const saved = upsertRule({
|
|
298
|
-
...draft,
|
|
299
|
-
id: editing.id
|
|
300
|
-
});
|
|
301
|
-
enforceRuleLimit(saved?.id ?? editing.id);
|
|
302
|
-
// Arm the master switch. Deliberately creating a rule and having it sit
|
|
303
|
-
// inert because overrides happen to be paused is the silent-failure this
|
|
304
|
-
// feature can least afford — the preset path already does this, and the
|
|
305
|
-
// manager disagreeing with it was just a gap.
|
|
306
|
-
setEnabled(true);
|
|
307
|
-
setEditing(null);
|
|
308
|
-
};
|
|
309
|
-
if (editing) {
|
|
310
|
-
return /*#__PURE__*/_jsx(NetworkOverrideEditor, {
|
|
311
|
-
draft: editing.draft,
|
|
312
|
-
onChange: draft => setEditing({
|
|
313
|
-
...editing,
|
|
314
|
-
draft
|
|
315
|
-
}),
|
|
316
|
-
onSave: handleSave,
|
|
317
|
-
onCancel: () => setEditing(null),
|
|
318
|
-
saveLabel: editing.id ? "Save" : "Add",
|
|
319
|
-
applySafeAreaInset: applySafeAreaInset
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
const hasRules = rules.length > 0;
|
|
323
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
324
|
-
style: styles.root,
|
|
325
|
-
children: [hasRules ? /*#__PURE__*/_jsxs(View, {
|
|
326
|
-
style: [styles.bar, enabled && activeCount > 0 && styles.barOn],
|
|
327
|
-
children: [enabled && activeCount > 0 ? /*#__PURE__*/_jsx(AlertTriangle, {
|
|
328
|
-
size: 12,
|
|
329
|
-
color: macOSColors.semantic.warning
|
|
330
|
-
}) : null, /*#__PURE__*/_jsx(Text, {
|
|
331
|
-
style: [styles.barText, enabled && activeCount > 0 && styles.barTextOn],
|
|
332
|
-
numberOfLines: 2,
|
|
333
|
-
children: autoPaused ? "Overrides paused — they'd been on for 3 launches" : enabled && activeCount > 0 ? `${activeCount} override${activeCount === 1 ? " is" : "s are"} on` : "Overrides are off"
|
|
334
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
335
|
-
onPress: () => setEnabled(!(enabled && activeCount > 0)),
|
|
336
|
-
"sentry-label": "ignore toggle overrides master",
|
|
337
|
-
testID: "buoy-network-overrides-master",
|
|
338
|
-
accessibilityRole: "button",
|
|
339
|
-
style: styles.barButton,
|
|
340
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
341
|
-
style: styles.barButtonText,
|
|
342
|
-
children: enabled && activeCount > 0 ? "Turn all off" : autoPaused ? "Turn back on" : "Turn on"
|
|
343
|
-
})
|
|
344
|
-
})]
|
|
345
|
-
}) : null, /*#__PURE__*/_jsxs(View, {
|
|
346
|
-
style: styles.listHeader,
|
|
347
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
348
|
-
style: styles.listHeaderText,
|
|
349
|
-
children: hasRules ? `${rules.length} rule${rules.length === 1 ? "" : "s"}` : ""
|
|
350
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
351
|
-
onPress: () => setEditing({
|
|
352
|
-
draft: blankDraft()
|
|
353
|
-
}),
|
|
354
|
-
"sentry-label": "ignore new override rule",
|
|
355
|
-
accessibilityLabel: "New override rule",
|
|
356
|
-
style: styles.newButton,
|
|
357
|
-
children: /*#__PURE__*/_jsx(Plus, {
|
|
358
|
-
size: 14,
|
|
359
|
-
color: macOSColors.semantic.info
|
|
360
|
-
})
|
|
361
|
-
})]
|
|
362
|
-
}), !hasRules ? /*#__PURE__*/_jsx(View, {
|
|
363
|
-
style: styles.emptyWrap,
|
|
364
|
-
children: /*#__PURE__*/_jsx(EmptyState
|
|
365
|
-
// Otto instead of the flask: nothing is faked yet, so he peers
|
|
366
|
-
// into an empty box. Truthful by construction — this branch only
|
|
367
|
-
// renders when the rule list is genuinely empty, and the master
|
|
368
|
-
// switch bar above is hidden in exactly that case.
|
|
369
|
-
, {
|
|
370
|
-
otto: "empty"
|
|
371
|
-
// 32 → pixelSize 2, the size the saved/list screens use, so the
|
|
372
|
-
// three network empties read as one family.
|
|
373
|
-
,
|
|
374
|
-
iconSize: 32,
|
|
375
|
-
title: "Nothing overridden"
|
|
376
|
-
// Names the control that actually exists. This said "tap Force 500"
|
|
377
|
-
// — a button from the deleted preset list, which sent anyone
|
|
378
|
-
// following it looking for something that isn't there.
|
|
379
|
-
,
|
|
380
|
-
description: "Open any request and tap Override, or + to write a rule."
|
|
381
|
-
})
|
|
382
|
-
}) : /*#__PURE__*/_jsxs(ScrollView, {
|
|
383
|
-
style: styles.list,
|
|
384
|
-
contentContainerStyle: styles.listContent,
|
|
385
|
-
keyboardShouldPersistTaps: "handled",
|
|
386
|
-
children: [rules.map(rule => /*#__PURE__*/_jsx(RuleRow, {
|
|
387
|
-
rule: rule,
|
|
388
|
-
spent: isRuleSpent(rule),
|
|
389
|
-
onEdit: () => openRule(rule),
|
|
390
|
-
onDelete: () => removeRule(rule.id)
|
|
391
|
-
}, rule.id)), ruleLimit < MAX_RULES ? /*#__PURE__*/_jsx(Text, {
|
|
392
|
-
style: styles.footNote,
|
|
393
|
-
children: `Your plan: ${ruleLimit} override at a time. Pro: up to ${MAX_RULES}.`
|
|
394
|
-
}) : null]
|
|
395
|
-
})]
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
const styles = StyleSheet.create({
|
|
399
|
-
root: {
|
|
400
|
-
flex: 1
|
|
401
|
-
},
|
|
402
|
-
bar: {
|
|
403
|
-
flexDirection: "row",
|
|
404
|
-
alignItems: "center",
|
|
405
|
-
gap: 8,
|
|
406
|
-
paddingHorizontal: 12,
|
|
407
|
-
paddingVertical: 10,
|
|
408
|
-
borderBottomWidth: 1,
|
|
409
|
-
borderBottomColor: macOSColors.border.default,
|
|
410
|
-
backgroundColor: macOSColors.background.card
|
|
411
|
-
},
|
|
412
|
-
barOn: {
|
|
413
|
-
borderBottomColor: macOSColors.semantic.warning + "44",
|
|
414
|
-
backgroundColor: macOSColors.semantic.warningBackground
|
|
415
|
-
},
|
|
416
|
-
barText: {
|
|
417
|
-
flex: 1,
|
|
418
|
-
fontSize: 12,
|
|
419
|
-
fontWeight: "600",
|
|
420
|
-
color: macOSColors.text.secondary
|
|
421
|
-
},
|
|
422
|
-
barTextOn: {
|
|
423
|
-
color: macOSColors.semantic.warning
|
|
424
|
-
},
|
|
425
|
-
barButton: {
|
|
426
|
-
paddingHorizontal: 10,
|
|
427
|
-
paddingVertical: 6,
|
|
428
|
-
borderRadius: 5,
|
|
429
|
-
borderWidth: 1,
|
|
430
|
-
borderColor: macOSColors.border.hover,
|
|
431
|
-
backgroundColor: macOSColors.background.base
|
|
432
|
-
},
|
|
433
|
-
barButtonText: {
|
|
434
|
-
fontSize: 11,
|
|
435
|
-
fontWeight: "700",
|
|
436
|
-
color: macOSColors.text.primary
|
|
437
|
-
},
|
|
438
|
-
listHeader: {
|
|
439
|
-
flexDirection: "row",
|
|
440
|
-
alignItems: "center",
|
|
441
|
-
justifyContent: "space-between",
|
|
442
|
-
paddingHorizontal: 12,
|
|
443
|
-
paddingTop: 10,
|
|
444
|
-
paddingBottom: 4
|
|
445
|
-
},
|
|
446
|
-
listHeaderText: {
|
|
447
|
-
fontSize: 10,
|
|
448
|
-
fontWeight: "700",
|
|
449
|
-
letterSpacing: 0.6,
|
|
450
|
-
color: macOSColors.text.muted,
|
|
451
|
-
textTransform: "uppercase"
|
|
452
|
-
},
|
|
453
|
-
newButton: {
|
|
454
|
-
padding: 6,
|
|
455
|
-
borderRadius: 5,
|
|
456
|
-
borderWidth: 1,
|
|
457
|
-
borderColor: macOSColors.border.default,
|
|
458
|
-
backgroundColor: macOSColors.background.card
|
|
459
|
-
},
|
|
460
|
-
emptyWrap: {
|
|
461
|
-
flex: 1,
|
|
462
|
-
justifyContent: "center"
|
|
463
|
-
},
|
|
464
|
-
list: {
|
|
465
|
-
flex: 1
|
|
466
|
-
},
|
|
467
|
-
listContent: {
|
|
468
|
-
padding: 10,
|
|
469
|
-
gap: 6
|
|
470
|
-
},
|
|
471
|
-
// The list already spaces rows via `listContent` gap — zero out the card's
|
|
472
|
-
// own margins so the two don't stack.
|
|
473
|
-
cardWrapper: {
|
|
474
|
-
marginHorizontal: 0,
|
|
475
|
-
marginVertical: 0
|
|
476
|
-
},
|
|
477
|
-
card: {
|
|
478
|
-
flexDirection: "row",
|
|
479
|
-
alignItems: "center",
|
|
480
|
-
gap: 8,
|
|
481
|
-
borderLeftWidth: 3,
|
|
482
|
-
borderLeftColor: "transparent"
|
|
483
|
-
},
|
|
484
|
-
cardMiddle: {
|
|
485
|
-
flex: 1
|
|
486
|
-
},
|
|
487
|
-
// Same type as the request row's URL.
|
|
488
|
-
urlText: {
|
|
489
|
-
fontSize: 12,
|
|
490
|
-
color: macOSColors.text.primary,
|
|
491
|
-
lineHeight: 16,
|
|
492
|
-
fontFamily: monoFont
|
|
493
|
-
},
|
|
494
|
-
urlTextOff: {
|
|
495
|
-
color: macOSColors.text.muted
|
|
496
|
-
},
|
|
497
|
-
extrasText: {
|
|
498
|
-
fontSize: 10,
|
|
499
|
-
color: macOSColors.text.secondary,
|
|
500
|
-
marginTop: 2
|
|
501
|
-
},
|
|
502
|
-
statusText: {
|
|
503
|
-
fontSize: 11,
|
|
504
|
-
fontWeight: "600"
|
|
505
|
-
},
|
|
506
|
-
failBadge: {
|
|
507
|
-
flexDirection: "row",
|
|
508
|
-
alignItems: "center",
|
|
509
|
-
gap: 2,
|
|
510
|
-
paddingHorizontal: 4,
|
|
511
|
-
paddingVertical: 1,
|
|
512
|
-
backgroundColor: macOSColors.semantic.error + "26",
|
|
513
|
-
borderRadius: 3
|
|
514
|
-
},
|
|
515
|
-
failText: {
|
|
516
|
-
fontSize: 10,
|
|
517
|
-
color: macOSColors.semantic.error,
|
|
518
|
-
fontWeight: "600"
|
|
519
|
-
},
|
|
520
|
-
rowHits: {
|
|
521
|
-
fontSize: 11,
|
|
522
|
-
fontWeight: "700",
|
|
523
|
-
color: macOSColors.semantic.warning
|
|
524
|
-
},
|
|
525
|
-
rowDelete: {
|
|
526
|
-
padding: 5,
|
|
527
|
-
borderRadius: 5,
|
|
528
|
-
borderWidth: 1,
|
|
529
|
-
borderColor: macOSColors.border.default,
|
|
530
|
-
backgroundColor: macOSColors.background.base
|
|
531
|
-
},
|
|
532
|
-
footNote: {
|
|
533
|
-
fontSize: 10,
|
|
534
|
-
lineHeight: 14,
|
|
535
|
-
color: macOSColors.text.muted,
|
|
536
|
-
paddingHorizontal: 4,
|
|
537
|
-
paddingTop: 8
|
|
538
|
-
}
|
|
539
|
-
});
|
|
1
|
+
"use strict";import{useCallback as I,useEffect as v,useState as j}from"react";import{ScrollView as N,StyleSheet as $,Text as u,TouchableOpacity as k,View as x}from"react-native";import{AlertCircle as M,AlertTriangle as _,DevToolsCard as V,EmptyState as F,MethodBadge as U,Plus as Y,Trash2 as q,macOSColors as t,useLimit as K,monoFont as X}from"@buoy-gg/shared-ui";import{useOverrideRules as G}from"../hooks/useOverrideRules";import{NetworkOverrideEditor as J}from"./NetworkOverrideEditor";import{overrideRulesStore as L}from"../overrides/overrideRulesStore";import{MAX_RULES as z}from"../overrides/types";import{jsx as o,jsxs as p}from"react/jsx-runtime";function Q(){return{enabled:true,urlPattern:"",kind:"respond",status:500,body:"",times:null}}function Z(e){const{id:i,hits:d,seen:f,createdAt:m,...g}=e;return g}function ee(e){const i=e.urlPattern;const d=i.indexOf("://");if(d===-1)return i;const f=i.indexOf("/",d+3);return f===-1?i.slice(d+3):i.slice(f)}function te(e){const i=[];if(e.delayMs)i.push(`${e.delayMs/1e3}s delay`);if(e.alternate)i.push("every other");else if(e.times===1)i.push("once");else if(typeof e.times==="number")i.push(`${e.times}\xD7`);return i.join(" \xB7 ")}function re(e){if(e.kind==="fail")return t.semantic.error;if(e.kind==="delay")return t.semantic.info;const i=e.status??200;if(i>=200&&i<300)return t.semantic.success;if(i>=300&&i<400)return t.semantic.info;return t.semantic.error}function ne({rule:e,spent:i,onEdit:d,onDelete:f}){const m=e.enabled&&!i;const g=re(e);const S=te(e);const T=e.methods?.length?e.methods.join("/"):"ANY";return p(V,{onPress:d,style:n.cardWrapper,contentStyle:[n.card,{borderLeftColor:m?g:"transparent"}],children:[o(U,{method:T,size:"small"}),p(x,{style:n.cardMiddle,children:[o(u,{style:[n.urlText,!m&&n.urlTextOff],numberOfLines:2,children:ee(e)}),S?o(u,{style:n.extrasText,children:S}):null]}),e.hits>0?o(u,{style:n.rowHits,children:e.hits}):null,e.kind==="fail"?p(x,{style:n.failBadge,children:[o(M,{size:10,color:t.semantic.error}),o(u,{style:n.failText,children:e.failKind==="timeout"?"TIMEOUT":"OFFLINE"})]}):o(u,{style:[n.statusText,{color:g}],children:e.kind==="delay"?"PASS":String(e.status??200)}),o(k,{onPress:f,"sentry-label":"ignore delete override rule",testID:"buoy-network-rule-delete",accessibilityRole:"button",accessibilityLabel:"Delete rule",hitSlop:{top:8,bottom:8,left:4,right:4},style:n.rowDelete,children:o(q,{size:13,color:t.text.muted})})]})}export function NetworkOverridesScreen(e){if(!e.visible)return null;return o(oe,{...e})}function oe({isPro:e,onUpgradePress:i,pendingDraft:d,onPendingConsumed:f,backHandlerRef:m,applySafeAreaInset:g}){const S=K("network.overrideRules");const T=e?z:S;const{enabled:y,autoPaused:R,rules:b,activeCount:h,setEnabled:B,upsertRule:P,setRuleEnabled:W,removeRule:E,isRuleSpent:w}=G();const[a,s]=j(null);v(()=>{L.noteHealthyLaunch()},[]);v(()=>{if(!m)return;m.current=a?()=>{s(null);return true}:null;return()=>{m.current=null}},[m,a]);const O=I(r=>{void L.fetchRuleBody(r).then(c=>{if(c==null)return;s(l=>l?.id===r?{...l,draft:{...l.draft,body:c,bodyOmitted:void 0}}:l)})},[]);v(()=>{if(!d)return;const{id:r,...c}=d;s({id:r,draft:c});if(r&&c.bodyOmitted)O(r);f?.()},[d,f,O]);v(()=>{if(!a?.id)return;if(b.some(r=>r.id===a.id))return;s(null)},[a?.id,b]);const H=r=>{s({id:r.id,draft:Z(r)});if(r.bodyOmitted)O(r.id)};const D=r=>{const c=b.filter(l=>l.enabled&&!w(l));if(c.length<=T)return;b.filter(l=>l.enabled&&!w(l)&&l.id!==r).forEach(l=>W(l.id,false))};const A=()=>{if(!a)return;const r={...a.draft,enabled:true,urlPattern:a.draft.urlPattern.trim()};if(!r.urlPattern)return;const c=P({...r,id:a.id});D(c?.id??a.id);B(true);s(null)};if(a){return o(J,{draft:a.draft,onChange:r=>s({...a,draft:r}),onSave:A,onCancel:()=>s(null),saveLabel:a.id?"Save":"Add",applySafeAreaInset:g})}const C=b.length>0;return p(x,{style:n.root,children:[C?p(x,{style:[n.bar,y&&h>0&&n.barOn],children:[y&&h>0?o(_,{size:12,color:t.semantic.warning}):null,o(u,{style:[n.barText,y&&h>0&&n.barTextOn],numberOfLines:2,children:R?"Overrides paused \u2014 they'd been on for 3 launches":y&&h>0?`${h} override${h===1?" is":"s are"} on`:"Overrides are off"}),o(k,{onPress:()=>B(!(y&&h>0)),"sentry-label":"ignore toggle overrides master",testID:"buoy-network-overrides-master",accessibilityRole:"button",style:n.barButton,children:o(u,{style:n.barButtonText,children:y&&h>0?"Turn all off":R?"Turn back on":"Turn on"})})]}):null,p(x,{style:n.listHeader,children:[o(u,{style:n.listHeaderText,children:C?`${b.length} rule${b.length===1?"":"s"}`:""}),o(k,{onPress:()=>s({draft:Q()}),"sentry-label":"ignore new override rule",accessibilityLabel:"New override rule",style:n.newButton,children:o(Y,{size:14,color:t.semantic.info})})]}),!C?o(x,{style:n.emptyWrap,children:o(F,{otto:"empty",iconSize:32,title:"Nothing overridden",description:"Open any request and tap Override, or + to write a rule."})}):p(N,{style:n.list,contentContainerStyle:n.listContent,keyboardShouldPersistTaps:"handled",children:[b.map(r=>o(ne,{rule:r,spent:w(r),onEdit:()=>H(r),onDelete:()=>E(r.id)},r.id)),T<z?o(u,{style:n.footNote,children:`Your plan: ${T} override at a time. Pro: up to ${z}.`}):null]})]})}const n=$.create({root:{flex:1},bar:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:12,paddingVertical:10,borderBottomWidth:1,borderBottomColor:t.border.default,backgroundColor:t.background.card},barOn:{borderBottomColor:t.semantic.warning+"44",backgroundColor:t.semantic.warningBackground},barText:{flex:1,fontSize:12,fontWeight:"600",color:t.text.secondary},barTextOn:{color:t.semantic.warning},barButton:{paddingHorizontal:10,paddingVertical:6,borderRadius:5,borderWidth:1,borderColor:t.border.hover,backgroundColor:t.background.base},barButtonText:{fontSize:11,fontWeight:"700",color:t.text.primary},listHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:12,paddingTop:10,paddingBottom:4},listHeaderText:{fontSize:10,fontWeight:"700",letterSpacing:.6,color:t.text.muted,textTransform:"uppercase"},newButton:{padding:6,borderRadius:5,borderWidth:1,borderColor:t.border.default,backgroundColor:t.background.card},emptyWrap:{flex:1,justifyContent:"center"},list:{flex:1},listContent:{padding:10,gap:6},cardWrapper:{marginHorizontal:0,marginVertical:0},card:{flexDirection:"row",alignItems:"center",gap:8,borderLeftWidth:3,borderLeftColor:"transparent"},cardMiddle:{flex:1},urlText:{fontSize:12,color:t.text.primary,lineHeight:16,fontFamily:X},urlTextOff:{color:t.text.muted},extrasText:{fontSize:10,color:t.text.secondary,marginTop:2},statusText:{fontSize:11,fontWeight:"600"},failBadge:{flexDirection:"row",alignItems:"center",gap:2,paddingHorizontal:4,paddingVertical:1,backgroundColor:t.semantic.error+"26",borderRadius:3},failText:{fontSize:10,color:t.semantic.error,fontWeight:"600"},rowHits:{fontSize:11,fontWeight:"700",color:t.semantic.warning},rowDelete:{padding:5,borderRadius:5,borderWidth:1,borderColor:t.border.default,backgroundColor:t.background.base},footNote:{fontSize:10,lineHeight:14,color:t.text.muted,paddingHorizontal:4,paddingTop:8}});
|