@buoy-gg/network 7.0.40 → 7.0.42

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.
Files changed (275) hide show
  1. package/README.md +11 -79
  2. package/lib/commonjs/index.js +1 -325
  3. package/lib/commonjs/index.web.js +1 -420
  4. package/lib/commonjs/network/components/DataViewer.web.js +1 -879
  5. package/lib/commonjs/network/components/NetworkCopyScreen.web.js +1 -48
  6. package/lib/commonjs/network/components/NetworkCopySettingsView.js +27 -755
  7. package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +14 -1242
  8. package/lib/commonjs/network/components/NetworkDetailScreen.web.js +1 -101
  9. package/lib/commonjs/network/components/NetworkDetailStepper.js +1 -108
  10. package/lib/commonjs/network/components/NetworkDetailStepper.web.js +1 -298
  11. package/lib/commonjs/network/components/NetworkEventDetailView.js +15 -1130
  12. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +15 -1484
  13. package/lib/commonjs/network/components/NetworkEventItemCompact.js +2 -401
  14. package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +2 -820
  15. package/lib/commonjs/network/components/NetworkFilterScreen.web.js +1 -55
  16. package/lib/commonjs/network/components/NetworkFilterViewV3.js +1 -442
  17. package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1 -1310
  18. package/lib/commonjs/network/components/NetworkHeaderLive.js +1 -375
  19. package/lib/commonjs/network/components/NetworkHeaderLive.web.js +1 -623
  20. package/lib/commonjs/network/components/NetworkHeaderMenu.js +1 -190
  21. package/lib/commonjs/network/components/NetworkListScreen.js +1 -404
  22. package/lib/commonjs/network/components/NetworkListScreen.web.js +1 -625
  23. package/lib/commonjs/network/components/NetworkModal.js +1 -786
  24. package/lib/commonjs/network/components/NetworkNumberPrompt.js +1 -178
  25. package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +1 -232
  26. package/lib/commonjs/network/components/NetworkOverrideEditor.js +1 -814
  27. package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +1 -942
  28. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.js +1 -107
  29. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +1 -133
  30. package/lib/commonjs/network/components/NetworkOverridesButton.js +1 -90
  31. package/lib/commonjs/network/components/NetworkOverridesButton.web.js +1 -143
  32. package/lib/commonjs/network/components/NetworkOverridesScreen.js +1 -543
  33. package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +1 -830
  34. package/lib/commonjs/network/components/NetworkSavedScreen.js +1 -226
  35. package/lib/commonjs/network/components/NetworkSavedScreen.web.js +1 -463
  36. package/lib/commonjs/network/components/NetworkUpgradeBanner.js +1 -76
  37. package/lib/commonjs/network/components/response-editor/Explorer.js +1 -973
  38. package/lib/commonjs/network/components/response-editor/Explorer.web.js +1 -1136
  39. package/lib/commonjs/network/components/response-editor/deleteNestedDataByPath.js +1 -56
  40. package/lib/commonjs/network/components/response-editor/editorContext.js +1 -33
  41. package/lib/commonjs/network/components/response-editor/updateNestedDataByPath.js +1 -61
  42. package/lib/commonjs/network/conditions/NetworkConditionsControl.js +1 -235
  43. package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +1 -136
  44. package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +1 -33
  45. package/lib/commonjs/network/conditions/NetworkFloatingTool.js +1 -310
  46. package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +1 -219
  47. package/lib/commonjs/network/conditions/store.js +1 -75
  48. package/lib/commonjs/network/conditions/wait.js +1 -43
  49. package/lib/commonjs/network/conditions/xhr.js +1 -110
  50. package/lib/commonjs/network/hooks/useLiveNetworkEvent.js +1 -62
  51. package/lib/commonjs/network/hooks/useNetworkBadgeCounts.js +1 -83
  52. package/lib/commonjs/network/hooks/useNetworkEventList.js +1 -108
  53. package/lib/commonjs/network/hooks/useNetworkEvents.js +1 -318
  54. package/lib/commonjs/network/hooks/useNetworkHasMatches.js +1 -56
  55. package/lib/commonjs/network/hooks/useNetworkSaved.js +1 -38
  56. package/lib/commonjs/network/hooks/useNetworkSelection.js +1 -53
  57. package/lib/commonjs/network/hooks/useOverrideRules.js +1 -36
  58. package/lib/commonjs/network/hooks/useTickEveryMinute.js +1 -21
  59. package/lib/commonjs/network/overrides/applyToFetch.js +1 -80
  60. package/lib/commonjs/network/overrides/applyToXhr.js +2 -453
  61. package/lib/commonjs/network/overrides/engine.js +1 -93
  62. package/lib/commonjs/network/overrides/matchRule.js +1 -81
  63. package/lib/commonjs/network/overrides/overriddenRows.js +1 -0
  64. package/lib/commonjs/network/overrides/overrideRulesStore.js +1 -550
  65. package/lib/commonjs/network/overrides/presets.js +1 -70
  66. package/lib/commonjs/network/overrides/resolveOverride.js +1 -158
  67. package/lib/commonjs/network/overrides/types.js +1 -90
  68. package/lib/commonjs/network/sync/networkBodyResolver.js +1 -39
  69. package/lib/commonjs/network/sync/networkSyncAdapter.js +1 -882
  70. package/lib/commonjs/network/sync/overrideHonesty.release.test.js +1 -36
  71. package/lib/commonjs/network/types/index.js +1 -5
  72. package/lib/commonjs/network/utils/extractOperationName.js +1 -80
  73. package/lib/commonjs/network/utils/filterNetworkEvents.js +1 -96
  74. package/lib/commonjs/network/utils/formatGraphQLVariables.js +1 -219
  75. package/lib/commonjs/network/utils/formatting.js +1 -30
  76. package/lib/commonjs/network/utils/generateCurl.js +2 -71
  77. package/lib/commonjs/network/utils/generateNetworkCopyText.js +37 -166
  78. package/lib/commonjs/network/utils/httpCompletion.js +1 -37
  79. package/lib/commonjs/network/utils/networkEventStore.js +1 -393
  80. package/lib/commonjs/network/utils/networkListener.js +4 -1259
  81. package/lib/commonjs/network/utils/networkSavedStore.js +3 -577
  82. package/lib/commonjs/network/utils/networkSelectionStore.js +1 -193
  83. package/lib/commonjs/network/utils/realNow.js +1 -0
  84. package/lib/commonjs/network/utils/requestId.js +1 -0
  85. package/lib/commonjs/network/utils/resolveRequestUrl.js +1 -0
  86. package/lib/commonjs/network/utils/selectSavedEvents.js +1 -39
  87. package/lib/commonjs/network/utils/startNetworkCapture.js +1 -0
  88. package/lib/commonjs/network/utils/withPinnedFirst.js +1 -32
  89. package/lib/commonjs/preset.js +1 -102
  90. package/lib/module/index.js +1 -103
  91. package/lib/module/index.web.js +1 -82
  92. package/lib/module/network/components/DataViewer.web.js +1 -875
  93. package/lib/module/network/components/NetworkCopyScreen.web.js +1 -44
  94. package/lib/module/network/components/NetworkCopySettingsView.js +27 -750
  95. package/lib/module/network/components/NetworkCopySettingsView.web.js +14 -1237
  96. package/lib/module/network/components/NetworkDetailScreen.web.js +1 -97
  97. package/lib/module/network/components/NetworkDetailStepper.js +1 -104
  98. package/lib/module/network/components/NetworkDetailStepper.web.js +1 -296
  99. package/lib/module/network/components/NetworkEventDetailView.js +15 -1129
  100. package/lib/module/network/components/NetworkEventDetailView.web.js +15 -1482
  101. package/lib/module/network/components/NetworkEventItemCompact.js +2 -398
  102. package/lib/module/network/components/NetworkEventItemCompact.web.js +2 -818
  103. package/lib/module/network/components/NetworkFilterScreen.web.js +1 -51
  104. package/lib/module/network/components/NetworkFilterViewV3.js +1 -438
  105. package/lib/module/network/components/NetworkFilterViewV3.web.js +1 -1306
  106. package/lib/module/network/components/NetworkHeaderLive.js +1 -366
  107. package/lib/module/network/components/NetworkHeaderLive.web.js +1 -617
  108. package/lib/module/network/components/NetworkHeaderMenu.js +1 -184
  109. package/lib/module/network/components/NetworkListScreen.js +1 -400
  110. package/lib/module/network/components/NetworkListScreen.web.js +1 -623
  111. package/lib/module/network/components/NetworkModal.js +1 -781
  112. package/lib/module/network/components/NetworkNumberPrompt.js +1 -174
  113. package/lib/module/network/components/NetworkNumberPrompt.web.js +1 -230
  114. package/lib/module/network/components/NetworkOverrideEditor.js +1 -811
  115. package/lib/module/network/components/NetworkOverrideEditor.web.js +1 -939
  116. package/lib/module/network/components/NetworkOverrideHeaderButton.js +1 -104
  117. package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +1 -131
  118. package/lib/module/network/components/NetworkOverridesButton.js +1 -87
  119. package/lib/module/network/components/NetworkOverridesButton.web.js +1 -141
  120. package/lib/module/network/components/NetworkOverridesScreen.js +1 -539
  121. package/lib/module/network/components/NetworkOverridesScreen.web.js +1 -826
  122. package/lib/module/network/components/NetworkSavedScreen.js +1 -222
  123. package/lib/module/network/components/NetworkSavedScreen.web.js +1 -461
  124. package/lib/module/network/components/NetworkUpgradeBanner.js +1 -72
  125. package/lib/module/network/components/response-editor/Explorer.js +1 -972
  126. package/lib/module/network/components/response-editor/Explorer.web.js +1 -1133
  127. package/lib/module/network/components/response-editor/deleteNestedDataByPath.js +1 -51
  128. package/lib/module/network/components/response-editor/editorContext.js +1 -29
  129. package/lib/module/network/components/response-editor/updateNestedDataByPath.js +1 -56
  130. package/lib/module/network/conditions/NetworkConditionsControl.js +1 -231
  131. package/lib/module/network/conditions/NetworkConditionsControl.test.js +1 -135
  132. package/lib/module/network/conditions/NetworkConditionsIcon.js +1 -29
  133. package/lib/module/network/conditions/NetworkFloatingTool.js +1 -304
  134. package/lib/module/network/conditions/NetworkFloatingTool.test.js +1 -218
  135. package/lib/module/network/conditions/store.js +1 -65
  136. package/lib/module/network/conditions/wait.js +1 -38
  137. package/lib/module/network/conditions/xhr.js +1 -106
  138. package/lib/module/network/hooks/useLiveNetworkEvent.js +1 -58
  139. package/lib/module/network/hooks/useNetworkBadgeCounts.js +1 -79
  140. package/lib/module/network/hooks/useNetworkEventList.js +1 -104
  141. package/lib/module/network/hooks/useNetworkEvents.js +1 -314
  142. package/lib/module/network/hooks/useNetworkHasMatches.js +1 -52
  143. package/lib/module/network/hooks/useNetworkSaved.js +1 -34
  144. package/lib/module/network/hooks/useNetworkSelection.js +1 -46
  145. package/lib/module/network/hooks/useOverrideRules.js +1 -32
  146. package/lib/module/network/hooks/useTickEveryMinute.js +1 -11
  147. package/lib/module/network/overrides/applyToFetch.js +1 -72
  148. package/lib/module/network/overrides/applyToXhr.js +2 -446
  149. package/lib/module/network/overrides/engine.js +1 -85
  150. package/lib/module/network/overrides/matchRule.js +1 -75
  151. package/lib/module/network/overrides/overriddenRows.js +1 -0
  152. package/lib/module/network/overrides/overrideRulesStore.js +1 -547
  153. package/lib/module/network/overrides/presets.js +1 -65
  154. package/lib/module/network/overrides/resolveOverride.js +1 -152
  155. package/lib/module/network/overrides/types.js +1 -86
  156. package/lib/module/network/sync/networkBodyResolver.js +1 -34
  157. package/lib/module/network/sync/networkSyncAdapter.js +1 -880
  158. package/lib/module/network/sync/overrideHonesty.release.test.js +1 -35
  159. package/lib/module/network/types/index.js +1 -3
  160. package/lib/module/network/utils/extractOperationName.js +1 -76
  161. package/lib/module/network/utils/filterNetworkEvents.js +1 -92
  162. package/lib/module/network/utils/formatGraphQLVariables.js +1 -213
  163. package/lib/module/network/utils/formatting.js +1 -9
  164. package/lib/module/network/utils/generateCurl.js +2 -67
  165. package/lib/module/network/utils/generateNetworkCopyText.js +37 -162
  166. package/lib/module/network/utils/httpCompletion.js +1 -32
  167. package/lib/module/network/utils/networkEventStore.js +1 -391
  168. package/lib/module/network/utils/networkListener.js +4 -1249
  169. package/lib/module/network/utils/networkSavedStore.js +3 -572
  170. package/lib/module/network/utils/networkSelectionStore.js +1 -188
  171. package/lib/module/network/utils/realNow.js +1 -0
  172. package/lib/module/network/utils/requestId.js +1 -0
  173. package/lib/module/network/utils/resolveRequestUrl.js +1 -0
  174. package/lib/module/network/utils/selectSavedEvents.js +1 -35
  175. package/lib/module/network/utils/startNetworkCapture.js +1 -0
  176. package/lib/module/network/utils/withPinnedFirst.js +1 -28
  177. package/lib/module/preset.js +1 -100
  178. package/lib/typescript/index.d.ts +1 -0
  179. package/lib/typescript/network/overrides/applyToXhr.d.ts +1 -0
  180. package/lib/typescript/network/overrides/engine.d.ts +1 -1
  181. package/lib/typescript/network/overrides/matchRule.d.ts +1 -1
  182. package/lib/typescript/network/overrides/overriddenRows.d.ts +16 -0
  183. package/lib/typescript/network/overrides/resolveOverride.d.ts +2 -2
  184. package/lib/typescript/network/overrides/types.d.ts +9 -0
  185. package/lib/typescript/network/utils/networkListener.d.ts +14 -4
  186. package/lib/typescript/network/utils/networkSavedStore.d.ts +4 -4
  187. package/lib/typescript/network/utils/realNow.d.ts +18 -0
  188. package/lib/typescript/network/utils/requestId.d.ts +2 -0
  189. package/lib/typescript/network/utils/resolveRequestUrl.d.ts +3 -0
  190. package/lib/typescript/network/utils/startNetworkCapture.d.ts +6 -0
  191. package/lib/web/index.mjs +145 -0
  192. package/package.json +32 -10
  193. package/lib/typescript/index.d.ts.map +0 -1
  194. package/lib/typescript/index.web.d.ts.map +0 -1
  195. package/lib/typescript/network/components/DataViewer.web.d.ts.map +0 -1
  196. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +0 -1
  197. package/lib/typescript/network/components/NetworkCopySettingsView.d.ts.map +0 -1
  198. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +0 -1
  199. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +0 -1
  200. package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +0 -1
  201. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +0 -1
  202. package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +0 -1
  203. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +0 -1
  204. package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +0 -1
  205. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +0 -1
  206. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +0 -1
  207. package/lib/typescript/network/components/NetworkFilterViewV3.d.ts.map +0 -1
  208. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +0 -1
  209. package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +0 -1
  210. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +0 -1
  211. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +0 -1
  212. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +0 -1
  213. package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +0 -1
  214. package/lib/typescript/network/components/NetworkModal.d.ts.map +0 -1
  215. package/lib/typescript/network/components/NetworkNumberPrompt.d.ts.map +0 -1
  216. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +0 -1
  217. package/lib/typescript/network/components/NetworkOverrideEditor.d.ts.map +0 -1
  218. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +0 -1
  219. package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts.map +0 -1
  220. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +0 -1
  221. package/lib/typescript/network/components/NetworkOverridesButton.d.ts.map +0 -1
  222. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +0 -1
  223. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +0 -1
  224. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +0 -1
  225. package/lib/typescript/network/components/NetworkSavedScreen.d.ts.map +0 -1
  226. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +0 -1
  227. package/lib/typescript/network/components/NetworkUpgradeBanner.d.ts.map +0 -1
  228. package/lib/typescript/network/components/response-editor/Explorer.d.ts.map +0 -1
  229. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +0 -1
  230. package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts.map +0 -1
  231. package/lib/typescript/network/components/response-editor/editorContext.d.ts.map +0 -1
  232. package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts.map +0 -1
  233. package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts.map +0 -1
  234. package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts.map +0 -1
  235. package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts.map +0 -1
  236. package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts.map +0 -1
  237. package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts.map +0 -1
  238. package/lib/typescript/network/conditions/store.d.ts.map +0 -1
  239. package/lib/typescript/network/conditions/wait.d.ts.map +0 -1
  240. package/lib/typescript/network/conditions/xhr.d.ts.map +0 -1
  241. package/lib/typescript/network/hooks/useLiveNetworkEvent.d.ts.map +0 -1
  242. package/lib/typescript/network/hooks/useNetworkBadgeCounts.d.ts.map +0 -1
  243. package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +0 -1
  244. package/lib/typescript/network/hooks/useNetworkEvents.d.ts.map +0 -1
  245. package/lib/typescript/network/hooks/useNetworkHasMatches.d.ts.map +0 -1
  246. package/lib/typescript/network/hooks/useNetworkSaved.d.ts.map +0 -1
  247. package/lib/typescript/network/hooks/useNetworkSelection.d.ts.map +0 -1
  248. package/lib/typescript/network/hooks/useOverrideRules.d.ts.map +0 -1
  249. package/lib/typescript/network/hooks/useTickEveryMinute.d.ts.map +0 -1
  250. package/lib/typescript/network/overrides/applyToFetch.d.ts.map +0 -1
  251. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +0 -1
  252. package/lib/typescript/network/overrides/engine.d.ts.map +0 -1
  253. package/lib/typescript/network/overrides/matchRule.d.ts.map +0 -1
  254. package/lib/typescript/network/overrides/overrideRulesStore.d.ts.map +0 -1
  255. package/lib/typescript/network/overrides/presets.d.ts.map +0 -1
  256. package/lib/typescript/network/overrides/resolveOverride.d.ts.map +0 -1
  257. package/lib/typescript/network/overrides/types.d.ts.map +0 -1
  258. package/lib/typescript/network/sync/networkBodyResolver.d.ts.map +0 -1
  259. package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +0 -1
  260. package/lib/typescript/network/sync/overrideHonesty.release.test.d.ts.map +0 -1
  261. package/lib/typescript/network/types/index.d.ts.map +0 -1
  262. package/lib/typescript/network/utils/extractOperationName.d.ts.map +0 -1
  263. package/lib/typescript/network/utils/filterNetworkEvents.d.ts.map +0 -1
  264. package/lib/typescript/network/utils/formatGraphQLVariables.d.ts.map +0 -1
  265. package/lib/typescript/network/utils/formatting.d.ts.map +0 -1
  266. package/lib/typescript/network/utils/generateCurl.d.ts.map +0 -1
  267. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +0 -1
  268. package/lib/typescript/network/utils/httpCompletion.d.ts.map +0 -1
  269. package/lib/typescript/network/utils/networkEventStore.d.ts.map +0 -1
  270. package/lib/typescript/network/utils/networkListener.d.ts.map +0 -1
  271. package/lib/typescript/network/utils/networkSavedStore.d.ts.map +0 -1
  272. package/lib/typescript/network/utils/networkSelectionStore.d.ts.map +0 -1
  273. package/lib/typescript/network/utils/selectSavedEvents.d.ts.map +0 -1
  274. package/lib/typescript/network/utils/withPinnedFirst.d.ts.map +0 -1
  275. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,304 +1 @@
1
- "use strict";
2
-
3
- import { useEffect, useRef, useState, useSyncExternalStore } from "react";
4
- import { ActivityIndicator, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions } from "react-native";
5
- import { FloatingTool, night, openFloatingTool, persistentStorage, registerPersistentFloatingTool } from "@buoy-gg/shared-ui";
6
- import { conditionsCanApply, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions } from "./store";
7
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
- /** A live source keeps the desktop strip current after its launching panel closes. */
9
- export function createRemoteConditionsSource() {
10
- let value;
11
- const listeners = new Set();
12
- return {
13
- getSnapshot: () => value,
14
- subscribe: listener => {
15
- listeners.add(listener);
16
- return () => {
17
- listeners.delete(listener);
18
- };
19
- },
20
- update(next) {
21
- value = next;
22
- listeners.forEach(listener => listener());
23
- }
24
- };
25
- }
26
- const noSubscribe = () => () => {};
27
- const noRemote = () => undefined;
28
- const options = [{
29
- id: "normal",
30
- label: "No throttling",
31
- detail: "No added delay"
32
- }, {
33
- id: "slow",
34
- label: "Slow",
35
- detail: "+500 ms before sending"
36
- }, {
37
- id: "verySlow",
38
- label: "Very slow",
39
- detail: "+2 seconds before sending"
40
- }, {
41
- id: "offline",
42
- label: "Offline",
43
- detail: "New requests fail"
44
- }];
45
- const localRegistration = {
46
- id: "network-throttling",
47
- render: context => /*#__PURE__*/_jsx(NetworkFloatingTool, {
48
- ...context
49
- })
50
- };
51
- if (typeof __DEV__ !== "undefined" && __DEV__ && typeof navigator !== "undefined" && navigator.product === "ReactNative") {
52
- registerPersistentFloatingTool(localRegistration, persistentStorage);
53
- }
54
- export function openNetworkFloatingTool(source) {
55
- openFloatingTool({
56
- id: "network-throttling",
57
- render: context => /*#__PURE__*/_jsx(NetworkFloatingTool, {
58
- ...context,
59
- source: source
60
- })
61
- });
62
- }
63
- export function NetworkFloatingTool({
64
- id,
65
- revealToken,
66
- dismiss,
67
- source
68
- }) {
69
- const local = useSyncExternalStore(subscribeNetworkConditions, getNetworkCondition, getNetworkCondition);
70
- const localAvailable = useSyncExternalStore(subscribeNetworkConditions, conditionsCanApply, conditionsCanApply);
71
- const remote = useSyncExternalStore(source?.subscribe ?? noSubscribe, source?.getSnapshot ?? noRemote, noRemote);
72
- const profile = source ? remote?.profile ?? null : local;
73
- const available = source ? remote?.available === true : localAvailable;
74
- const [pending, setPending] = useState(false);
75
- const [error, setError] = useState();
76
- const busy = useRef(false);
77
- const operation = useRef(0);
78
- const mounted = useRef(true);
79
- const {
80
- width
81
- } = useWindowDimensions();
82
- useEffect(() => {
83
- mounted.current = true;
84
- return () => {
85
- mounted.current = false;
86
- };
87
- }, []);
88
- useEffect(() => {
89
- operation.current += 1;
90
- busy.current = false;
91
- setPending(false);
92
- setError(undefined);
93
- }, [source, remote?.targetId]);
94
- const active = profile !== null && profile !== "normal";
95
- const selected = profile ?? "normal";
96
- const choice = options.find(option => option.id === selected);
97
- const next = options[(options.findIndex(option => option.id === selected) + 1) % options.length];
98
- const bars = !available || selected === "offline" ? 0 : selected === "verySlow" ? 1 : selected === "slow" ? 2 : 4;
99
- const detail = pending ? "Applying…" : !available ? "Unavailable" : selected === "normal" ? "0 ms" : selected === "slow" ? "+500 ms" : selected === "verySlow" ? "+2000 ms" : "Blocked";
100
- async function apply(next, close = false) {
101
- if (busy.current) return;
102
- const currentOperation = ++operation.current;
103
- busy.current = true;
104
- setPending(true);
105
- setError(undefined);
106
- const startingRemote = source?.getSnapshot();
107
- try {
108
- if (source) {
109
- if (!startingRemote?.available) throw new Error("Device unavailable. Open Network again to reconnect these controls.");
110
- await startingRemote.onChange(next);
111
- } else setNetworkCondition(next);
112
- if (mounted.current && operation.current === currentOperation) {
113
- if (close) dismiss();
114
- }
115
- } catch (failure) {
116
- if (mounted.current && operation.current === currentOperation) setError(failure instanceof Error ? failure.message : String(failure));
117
- } finally {
118
- if (operation.current === currentOperation) {
119
- busy.current = false;
120
- if (mounted.current) setPending(false);
121
- }
122
- }
123
- }
124
- const accessory = error ? /*#__PURE__*/_jsx(View, {
125
- style: styles.menu,
126
- children: /*#__PURE__*/_jsx(Text, {
127
- accessibilityRole: "alert",
128
- style: styles.error,
129
- children: error
130
- })
131
- }) : undefined;
132
- return /*#__PURE__*/_jsx(FloatingTool, {
133
- id: id,
134
- revealToken: revealToken,
135
- variant: "strip",
136
- dragFromSurface: true,
137
- accessibilityLabel: `Move or hide network throttling. ${active ? "Active" : "Off"}`,
138
- accessory: accessory,
139
- children: /*#__PURE__*/_jsxs(View, {
140
- style: [styles.row, {
141
- width: Math.max(220, Math.min(292, width - 64))
142
- }],
143
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
144
- testID: "throttling-cycle",
145
- accessibilityRole: "button",
146
- accessibilityLabel: `Network: ${choice.label}. Switch to ${next.label}`,
147
- accessibilityState: {
148
- disabled: pending || !available
149
- },
150
- disabled: pending || !available,
151
- onPress: () => void apply(next.id),
152
- style: styles.signalButton,
153
- children: pending ? /*#__PURE__*/_jsx(ActivityIndicator, {
154
- size: "small",
155
- color: night.color.accent
156
- }) : /*#__PURE__*/_jsxs(View, {
157
- testID: `throttling-signal-${selected}`,
158
- style: styles.signal,
159
- children: [[7, 12, 18, 24].map((height, index) => /*#__PURE__*/_jsx(View, {
160
- style: {
161
- width: 4,
162
- height,
163
- borderRadius: 2,
164
- backgroundColor: index < bars ? selected === "offline" ? night.color.danger : night.color.accent : night.color.fillTertiary
165
- }
166
- }, height)), selected === "offline" && /*#__PURE__*/_jsx(View, {
167
- style: styles.slash
168
- })]
169
- })
170
- }), /*#__PURE__*/_jsx(View, {
171
- style: styles.profile,
172
- children: /*#__PURE__*/_jsx(Text, {
173
- testID: "throttling-profile",
174
- accessibilityLabel: `Connection profile: ${choice.label}`,
175
- accessibilityLiveRegion: "polite",
176
- numberOfLines: 1,
177
- style: styles.profileLabel,
178
- children: choice.label
179
- })
180
- }), /*#__PURE__*/_jsx(Text, {
181
- testID: "throttling-status",
182
- numberOfLines: 1,
183
- accessibilityLiveRegion: "polite",
184
- style: styles.status,
185
- children: detail
186
- }), /*#__PURE__*/_jsx(View, {
187
- style: styles.separator
188
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
189
- testID: "throttling-close",
190
- accessibilityRole: "button",
191
- accessibilityLabel: "Close and turn off throttling",
192
- disabled: pending,
193
- accessibilityState: {
194
- disabled: pending
195
- },
196
- onPress: () => {
197
- if (profile === "normal") dismiss();else void apply("normal", true);
198
- },
199
- style: [styles.action, pending && styles.disabled],
200
- children: /*#__PURE__*/_jsx(Text, {
201
- style: styles.actionText,
202
- children: "Close"
203
- })
204
- })]
205
- })
206
- });
207
- }
208
- const styles = StyleSheet.create({
209
- row: {
210
- flexDirection: "row",
211
- alignItems: "center",
212
- gap: 6,
213
- paddingVertical: 4,
214
- minHeight: 48
215
- },
216
- signalButton: {
217
- width: 36,
218
- minHeight: 44,
219
- alignItems: "center",
220
- justifyContent: "center"
221
- },
222
- signal: {
223
- flexDirection: "row",
224
- alignItems: "flex-end",
225
- gap: 3,
226
- height: 24
227
- },
228
- slash: {
229
- position: "absolute",
230
- width: 30,
231
- height: 2,
232
- backgroundColor: night.color.danger,
233
- top: 11,
234
- left: -2,
235
- transform: [{
236
- rotate: "-45deg"
237
- }]
238
- },
239
- separator: {
240
- height: 20,
241
- width: 1,
242
- backgroundColor: night.color.separator,
243
- marginHorizontal: 2
244
- },
245
- status: {
246
- color: night.color.textSecondary,
247
- fontSize: 10,
248
- lineHeight: 15,
249
- flexShrink: 1
250
- },
251
- profile: {
252
- flex: 1,
253
- flexDirection: "row",
254
- alignItems: "center",
255
- gap: 6,
256
- minHeight: 44
257
- },
258
- profileLabel: {
259
- color: night.color.text,
260
- fontSize: 13,
261
- fontWeight: "500",
262
- flexShrink: 1
263
- },
264
- action: {
265
- minHeight: 36,
266
- minWidth: 52,
267
- borderRadius: night.radius.input,
268
- borderWidth: 1,
269
- borderColor: night.color.accentBorderStrong,
270
- alignItems: "center",
271
- justifyContent: "center",
272
- paddingHorizontal: 10
273
- },
274
- actionText: {
275
- color: night.color.accent,
276
- fontSize: 12,
277
- fontWeight: "600"
278
- },
279
- disabled: {
280
- opacity: 0.4
281
- },
282
- menu: {
283
- marginVertical: 8,
284
- padding: 6,
285
- borderRadius: night.radius.card,
286
- borderWidth: 1,
287
- borderColor: night.color.separator,
288
- backgroundColor: night.color.surface,
289
- shadowColor: "#000",
290
- shadowOffset: {
291
- width: 0,
292
- height: 6
293
- },
294
- shadowOpacity: 0.25,
295
- shadowRadius: 16,
296
- elevation: 8
297
- },
298
- error: {
299
- color: night.color.danger,
300
- fontSize: 12,
301
- lineHeight: 18,
302
- padding: 10
303
- }
304
- });
1
+ "use strict";import{useEffect as _,useRef as R,useState as O,useSyncExternalStore as I}from"react";import{ActivityIndicator as U,StyleSheet as G,Text as p,TouchableOpacity as E,View as d,useWindowDimensions as J}from"react-native";import{FloatingTool as K,night as e,openFloatingTool as Q,persistentStorage as X,registerPersistentFloatingTool as Y}from"@buoy-gg/shared-ui";import{conditionsCanApply as H,getNetworkCondition as z,setNetworkCondition as Z,subscribeNetworkConditions as j}from"./store";import{jsx as t,jsxs as F}from"react/jsx-runtime";export function createRemoteConditionsSource(){let l;const a=new Set;return{getSnapshot:()=>l,subscribe:s=>{a.add(s);return()=>{a.delete(s)}},update(s){l=s;a.forEach(r=>r())}}}const ee=()=>()=>{};const V=()=>void 0;const y=[{id:"normal",label:"No throttling",detail:"No added delay"},{id:"slow",label:"Slow",detail:"+500 ms before sending"},{id:"verySlow",label:"Very slow",detail:"+2 seconds before sending"},{id:"offline",label:"Offline",detail:"New requests fail"}];const te={id:"network-throttling",render:l=>t(NetworkFloatingTool,{...l})};if(typeof __DEV__!=="undefined"&&__DEV__&&typeof navigator!=="undefined"&&navigator.product==="ReactNative"){Y(te,X)}export function openNetworkFloatingTool(l){Q({id:"network-throttling",render:a=>t(NetworkFloatingTool,{...a,source:l})})}export function NetworkFloatingTool({id:l,revealToken:a,dismiss:s,source:r}){const W=I(j,z,z);const A=I(j,H,H);const m=I(r?.subscribe??ee,r?.getSnapshot??V,V);const g=r?m?.profile??null:W;const h=r?m?.available===true:A;const[c,w]=O(false);const[D,S]=O();const b=R(false);const f=R(0);const u=R(true);const{width:$}=J();_(()=>{u.current=true;return()=>{u.current=false}},[]);_(()=>{f.current+=1;b.current=false;w(false);S(void 0)},[r,m?.targetId]);const B=g!==null&&g!=="normal";const i=g??"normal";const v=y.find(n=>n.id===i);const N=y[(y.findIndex(n=>n.id===i)+1)%y.length];const P=!h||i==="offline"?0:i==="verySlow"?1:i==="slow"?2:4;const M=c?"Applying\u2026":!h?"Unavailable":i==="normal"?"0 ms":i==="slow"?"+500 ms":i==="verySlow"?"+2000 ms":"Blocked";async function T(n,x=false){if(b.current)return;const k=++f.current;b.current=true;w(true);S(void 0);const L=r?.getSnapshot();try{if(r){if(!L?.available)throw new Error("Device unavailable. Open Network again to reconnect these controls.");await L.onChange(n)}else Z(n);if(u.current&&f.current===k){if(x)s()}}catch(C){if(u.current&&f.current===k)S(C instanceof Error?C.message:String(C))}finally{if(f.current===k){b.current=false;if(u.current)w(false)}}}const q=D?t(d,{style:o.menu,children:t(p,{accessibilityRole:"alert",style:o.error,children:D})}):void 0;return t(K,{id:l,revealToken:a,variant:"strip",dragFromSurface:true,accessibilityLabel:`Move or hide network throttling. ${B?"Active":"Off"}`,accessory:q,children:F(d,{style:[o.row,{width:Math.max(220,Math.min(292,$-64))}],children:[t(E,{testID:"throttling-cycle",accessibilityRole:"button",accessibilityLabel:`Network: ${v.label}. Switch to ${N.label}`,accessibilityState:{disabled:c||!h},disabled:c||!h,onPress:()=>void T(N.id),style:o.signalButton,children:c?t(U,{size:"small",color:e.color.accent}):F(d,{testID:`throttling-signal-${i}`,style:o.signal,children:[[7,12,18,24].map((n,x)=>t(d,{style:{width:4,height:n,borderRadius:2,backgroundColor:x<P?i==="offline"?e.color.danger:e.color.accent:e.color.fillTertiary}},n)),i==="offline"&&t(d,{style:o.slash})]})}),t(d,{style:o.profile,children:t(p,{testID:"throttling-profile",accessibilityLabel:`Connection profile: ${v.label}`,accessibilityLiveRegion:"polite",numberOfLines:1,style:o.profileLabel,children:v.label})}),t(p,{testID:"throttling-status",numberOfLines:1,accessibilityLiveRegion:"polite",style:o.status,children:M}),t(d,{style:o.separator}),t(E,{testID:"throttling-close",accessibilityRole:"button",accessibilityLabel:"Close and turn off throttling",disabled:c,accessibilityState:{disabled:c},onPress:()=>{if(g==="normal")s();else void T("normal",true)},style:[o.action,c&&o.disabled],children:t(p,{style:o.actionText,children:"Close"})})]})})}const o=G.create({row:{flexDirection:"row",alignItems:"center",gap:6,paddingVertical:4,minHeight:48},signalButton:{width:36,minHeight:44,alignItems:"center",justifyContent:"center"},signal:{flexDirection:"row",alignItems:"flex-end",gap:3,height:24},slash:{position:"absolute",width:30,height:2,backgroundColor:e.color.danger,top:11,left:-2,transform:[{rotate:"-45deg"}]},separator:{height:20,width:1,backgroundColor:e.color.separator,marginHorizontal:2},status:{color:e.color.textSecondary,fontSize:10,lineHeight:15,flexShrink:1},profile:{flex:1,flexDirection:"row",alignItems:"center",gap:6,minHeight:44},profileLabel:{color:e.color.text,fontSize:13,fontWeight:"500",flexShrink:1},action:{minHeight:36,minWidth:52,borderRadius:e.radius.input,borderWidth:1,borderColor:e.color.accentBorderStrong,alignItems:"center",justifyContent:"center",paddingHorizontal:10},actionText:{color:e.color.accent,fontSize:12,fontWeight:"600"},disabled:{opacity:.4},menu:{marginVertical:8,padding:6,borderRadius:e.radius.card,borderWidth:1,borderColor:e.color.separator,backgroundColor:e.color.surface,shadowColor:"#000",shadowOffset:{width:0,height:6},shadowOpacity:.25,shadowRadius:16,elevation:8},error:{color:e.color.danger,fontSize:12,lineHeight:18,padding:10}});
@@ -1,218 +1 @@
1
- "use strict";
2
-
3
- // @vitest-environment jsdom
4
- import { act, createElement } from "react";
5
- import { createRoot } from "react-dom/client";
6
- import { afterEach, beforeEach, expect, it, vi } from "vitest";
7
- import { NetworkFloatingTool, createRemoteConditionsSource } from "./NetworkFloatingTool";
8
- const state = vi.hoisted(() => ({
9
- profile: "normal",
10
- available: true,
11
- listeners: new Set(),
12
- set: vi.fn()
13
- }));
14
- vi.mock("./store", () => ({
15
- getNetworkCondition: () => state.profile,
16
- conditionsCanApply: () => state.available,
17
- subscribeNetworkConditions: listener => {
18
- state.listeners.add(listener);
19
- return () => state.listeners.delete(listener);
20
- },
21
- setNetworkCondition: profile => {
22
- state.set(profile);
23
- state.profile = profile;
24
- state.listeners.forEach(listener => listener());
25
- }
26
- }));
27
- vi.mock("@buoy-gg/shared-ui", async () => ({
28
- night: (await vi.importActual("../../../../shared/src/ui/night/nightTheme")).night,
29
- ChevronDown: () => null,
30
- Check: () => null,
31
- openFloatingTool: vi.fn(),
32
- FloatingTool: ({
33
- children,
34
- accessory
35
- }) => /*#__PURE__*/createElement("div", null, children, accessory)
36
- }));
37
- vi.mock("react-native", () => ({
38
- StyleSheet: {
39
- create: value => value
40
- },
41
- useWindowDimensions: () => ({
42
- width: 390,
43
- height: 844
44
- }),
45
- View: ({
46
- children,
47
- testID
48
- }) => /*#__PURE__*/createElement("div", {
49
- "data-testid": testID
50
- }, children),
51
- Text: ({
52
- children,
53
- testID
54
- }) => /*#__PURE__*/createElement("span", {
55
- "data-testid": testID
56
- }, children),
57
- ActivityIndicator: () => null,
58
- TouchableOpacity: ({
59
- children,
60
- onPress,
61
- disabled,
62
- testID,
63
- accessibilityLabel
64
- }) => /*#__PURE__*/createElement("button", {
65
- onClick: onPress,
66
- disabled,
67
- "data-testid": testID,
68
- "aria-label": accessibilityLabel
69
- }, children)
70
- }));
71
- let root;
72
- let container;
73
- const dismiss = vi.fn();
74
- beforeEach(() => {
75
- globalThis.IS_REACT_ACT_ENVIRONMENT = true;
76
- state.profile = "normal";
77
- state.available = true;
78
- state.set.mockClear();
79
- dismiss.mockClear();
80
- container = document.createElement("div");
81
- root = createRoot(container);
82
- });
83
- afterEach(() => act(() => root.unmount()));
84
- const button = id => container.querySelector(`[data-testid="${id}"]`);
85
- const tap = async id => act(async () => button(id).click());
86
- const status = () => container.querySelector('[data-testid="throttling-status"]')?.textContent;
87
- function render(source) {
88
- act(() => root.render(/*#__PURE__*/createElement(NetworkFloatingTool, {
89
- id: "network-throttling",
90
- revealToken: 1,
91
- dismiss,
92
- source
93
- })));
94
- }
95
- async function choose(value) {
96
- const order = ["normal", "slow", "verySlow", "offline"];
97
- const count = (order.indexOf(value) - order.indexOf(state.profile) + order.length) % order.length;
98
- for (let i = 0; i < count; i++) await tap("throttling-cycle");
99
- }
100
- it("cycles and applies every profile immediately, including wrapping to normal", async () => {
101
- render();
102
- for (const [profile, label] of [["slow", "+500 ms"], ["verySlow", "+2000 ms"], ["offline", "Blocked"], ["normal", "0 ms"]]) {
103
- await tap("throttling-cycle");
104
- expect(state.profile).toBe(profile);
105
- expect(container.querySelector(`[data-testid="throttling-signal-${profile}"]`)).not.toBeNull();
106
- expect(status()).toBe(label);
107
- }
108
- expect(state.set).toHaveBeenCalledTimes(4);
109
- });
110
- it("keeps the profile label informational when tapped", async () => {
111
- render();
112
- await tap("throttling-profile");
113
- expect(state.set).not.toHaveBeenCalled();
114
- expect(state.profile).toBe("normal");
115
- expect(button("throttling-profile").closest("button")).toBeNull();
116
- });
117
- it("changes active profiles and stops before dismissal", async () => {
118
- state.profile = "slow";
119
- render();
120
- await choose("offline");
121
- expect(state.profile).toBe("offline");
122
- await tap("throttling-close");
123
- expect(state.profile).toBe("normal");
124
- expect(dismiss).toHaveBeenCalledOnce();
125
- });
126
- it("reflects external changes and disables cycling when account admission is revoked", () => {
127
- render();
128
- act(() => {
129
- state.profile = "offline";
130
- state.listeners.forEach(listener => listener());
131
- });
132
- expect(status()).toBe("Blocked");
133
- act(() => {
134
- state.profile = "normal";
135
- state.available = false;
136
- state.listeners.forEach(listener => listener());
137
- });
138
- expect(status()).toBe("Unavailable");
139
- expect(button("throttling-cycle").disabled).toBe(true);
140
- });
141
- it("keeps remote failures visible and does not claim a profile was applied", async () => {
142
- const source = createRemoteConditionsSource();
143
- const onChange = vi.fn().mockRejectedValue(new Error("Connection lost"));
144
- source.update({
145
- profile: "normal",
146
- available: true,
147
- onChange
148
- });
149
- render(source);
150
- await choose("slow");
151
- expect(container.textContent).toContain("Connection lost");
152
- expect(status()).toBe("0 ms");
153
- expect(state.set).not.toHaveBeenCalled();
154
- });
155
- it("prevents duplicate remote operations and follows confirmed snapshots", async () => {
156
- const source = createRemoteConditionsSource();
157
- let resolve;
158
- const onChange = vi.fn(() => new Promise(done => {
159
- resolve = done;
160
- }));
161
- source.update({
162
- profile: "normal",
163
- available: true,
164
- onChange
165
- });
166
- render(source);
167
- await tap("throttling-cycle");
168
- await tap("throttling-cycle");
169
- expect(onChange).toHaveBeenCalledOnce();
170
- expect(status()).toBe("Applying…");
171
- await act(async () => resolve());
172
- expect(status()).toBe("0 ms");
173
- act(() => source.update({
174
- profile: "slow",
175
- available: true,
176
- onChange
177
- }));
178
- expect(status()).toBe("+500 ms");
179
- act(() => source.update(undefined));
180
- expect(status()).toBe("Unavailable");
181
- });
182
- it("ignores a previous device's completion after switching devices", async () => {
183
- const source = createRemoteConditionsSource();
184
- let reject;
185
- source.update({
186
- targetId: "first",
187
- profile: "normal",
188
- available: true,
189
- onChange: () => new Promise((_resolve, fail) => {
190
- reject = fail;
191
- })
192
- });
193
- render(source);
194
- await choose("slow");
195
- act(() => source.update({
196
- targetId: "second",
197
- profile: "normal",
198
- available: true,
199
- onChange: vi.fn()
200
- }));
201
- await act(async () => reject(new Error("Old device failed")));
202
- expect(container.textContent).not.toContain("Old device failed");
203
- expect(status()).toBe("0 ms");
204
- expect(button("throttling-profile").textContent).toBe("No throttling");
205
- });
206
- it("keeps the strip open when stopping a remote device fails", async () => {
207
- const source = createRemoteConditionsSource();
208
- source.update({
209
- profile: "offline",
210
- available: true,
211
- onChange: vi.fn().mockRejectedValue(new Error("Could not stop"))
212
- });
213
- render(source);
214
- await tap("throttling-close");
215
- expect(dismiss).not.toHaveBeenCalled();
216
- expect(status()).toBe("Blocked");
217
- expect(container.textContent).toContain("Could not stop");
218
- });
1
+ "use strict";import{act as l,createElement as u}from"react";import{createRoot as y}from"react-dom/client";import{afterEach as b,beforeEach as B,expect as t,it as c,vi as a}from"vitest";import{NetworkFloatingTool as k,createRemoteConditionsSource as m}from"./NetworkFloatingTool";const n=a.hoisted(()=>({profile:"normal",available:true,listeners:new Set,set:a.fn()}));a.mock("./store",()=>({getNetworkCondition:()=>n.profile,conditionsCanApply:()=>n.available,subscribeNetworkConditions:e=>{n.listeners.add(e);return()=>n.listeners.delete(e)},setNetworkCondition:e=>{n.set(e);n.profile=e;n.listeners.forEach(o=>o())}}));a.mock("@buoy-gg/shared-ui",async()=>({night:(await a.importActual("../../../../shared/src/ui/night/nightTheme")).night,ChevronDown:()=>null,Check:()=>null,openFloatingTool:a.fn(),FloatingTool:({children:e,accessory:o})=>u("div",null,e,o)}));a.mock("react-native",()=>({StyleSheet:{create:e=>e},useWindowDimensions:()=>({width:390,height:844}),View:({children:e,testID:o})=>u("div",{"data-testid":o},e),Text:({children:e,testID:o})=>u("span",{"data-testid":o},e),ActivityIndicator:()=>null,TouchableOpacity:({children:e,onPress:o,disabled:r,testID:s,accessibilityLabel:C})=>u("button",{onClick:o,disabled:r,"data-testid":s,"aria-label":C},e)}));let w;let d;const h=a.fn();B(()=>{globalThis.IS_REACT_ACT_ENVIRONMENT=true;n.profile="normal";n.available=true;n.set.mockClear();h.mockClear();d=document.createElement("div");w=y(d)});b(()=>l(()=>w.unmount()));const g=e=>d.querySelector(`[data-testid="${e}"]`);const p=async e=>l(async()=>g(e).click());const i=()=>d.querySelector('[data-testid="throttling-status"]')?.textContent;function f(e){l(()=>w.render(u(k,{id:"network-throttling",revealToken:1,dismiss:h,source:e})))}async function v(e){const o=["normal","slow","verySlow","offline"];const r=(o.indexOf(e)-o.indexOf(n.profile)+o.length)%o.length;for(let s=0;s<r;s++)await p("throttling-cycle")}c("cycles and applies every profile immediately, including wrapping to normal",async()=>{f();for(const[e,o]of[["slow","+500 ms"],["verySlow","+2000 ms"],["offline","Blocked"],["normal","0 ms"]]){await p("throttling-cycle");t(n.profile).toBe(e);t(d.querySelector(`[data-testid="throttling-signal-${e}"]`)).not.toBeNull();t(i()).toBe(o)}t(n.set).toHaveBeenCalledTimes(4)});c("keeps the profile label informational when tapped",async()=>{f();await p("throttling-profile");t(n.set).not.toHaveBeenCalled();t(n.profile).toBe("normal");t(g("throttling-profile").closest("button")).toBeNull()});c("changes active profiles and stops before dismissal",async()=>{n.profile="slow";f();await v("offline");t(n.profile).toBe("offline");await p("throttling-close");t(n.profile).toBe("normal");t(h).toHaveBeenCalledOnce()});c("reflects external changes and disables cycling when account admission is revoked",()=>{f();l(()=>{n.profile="offline";n.listeners.forEach(e=>e())});t(i()).toBe("Blocked");l(()=>{n.profile="normal";n.available=false;n.listeners.forEach(e=>e())});t(i()).toBe("Unavailable");t(g("throttling-cycle").disabled).toBe(true)});c("keeps remote failures visible and does not claim a profile was applied",async()=>{const e=m();const o=a.fn().mockRejectedValue(new Error("Connection lost"));e.update({profile:"normal",available:true,onChange:o});f(e);await v("slow");t(d.textContent).toContain("Connection lost");t(i()).toBe("0 ms");t(n.set).not.toHaveBeenCalled()});c("prevents duplicate remote operations and follows confirmed snapshots",async()=>{const e=m();let o;const r=a.fn(()=>new Promise(s=>{o=s}));e.update({profile:"normal",available:true,onChange:r});f(e);await p("throttling-cycle");await p("throttling-cycle");t(r).toHaveBeenCalledOnce();t(i()).toBe("Applying\u2026");await l(async()=>o());t(i()).toBe("0 ms");l(()=>e.update({profile:"slow",available:true,onChange:r}));t(i()).toBe("+500 ms");l(()=>e.update(void 0));t(i()).toBe("Unavailable")});c("ignores a previous device's completion after switching devices",async()=>{const e=m();let o;e.update({targetId:"first",profile:"normal",available:true,onChange:()=>new Promise((r,s)=>{o=s})});f(e);await v("slow");l(()=>e.update({targetId:"second",profile:"normal",available:true,onChange:a.fn()}));await l(async()=>o(new Error("Old device failed")));t(d.textContent).not.toContain("Old device failed");t(i()).toBe("0 ms");t(g("throttling-profile").textContent).toBe("No throttling")});c("keeps the strip open when stopping a remote device fails",async()=>{const e=m();e.update({profile:"offline",available:true,onChange:a.fn().mockRejectedValue(new Error("Could not stop"))});f(e);await p("throttling-close");t(h).not.toHaveBeenCalled();t(i()).toBe("Blocked");t(d.textContent).toContain("Could not stop")});
@@ -1,65 +1 @@
1
- "use strict";
2
-
3
- import { hasAccountAccess, subscribeAccountAccess } from "@buoy-gg/shared-ui";
4
- import { addNetworkListener, startNetworkListener, getNetworkListenerCount, stopNetworkListener } from "../utils/networkListener";
5
- export const NETWORK_CONDITIONS = {
6
- normal: {
7
- label: "Normal",
8
- delayMs: 0
9
- },
10
- offline: {
11
- label: "Offline (requests)",
12
- delayMs: 0
13
- },
14
- slow: {
15
- label: "Slow (+500 ms)",
16
- delayMs: 500
17
- },
18
- verySlow: {
19
- label: "Very slow (+2000 ms)",
20
- delayMs: 2000
21
- }
22
- };
23
- export const networkConditionsRuntimeId = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
24
- let profile = "normal";
25
- let keepAlive;
26
- const listeners = new Set();
27
- export const conditionsCanApply = () => typeof __DEV__ !== "undefined" && __DEV__ && hasAccountAccess();
28
- export const getNetworkCondition = () => profile;
29
- export const subscribeNetworkConditions = listener => {
30
- listeners.add(listener);
31
- return () => {
32
- listeners.delete(listener);
33
- };
34
- };
35
- export function setNetworkCondition(value) {
36
- if (typeof value !== "string" || !Object.prototype.hasOwnProperty.call(NETWORK_CONDITIONS, value)) {
37
- throw new Error("Choose normal, offline, slow, or verySlow.");
38
- }
39
- if (value !== "normal" && !conditionsCanApply()) {
40
- throw new Error("Network conditions require an admitted account and a development build.");
41
- }
42
- if (value === profile) return profile;
43
- if (value !== "normal" && !keepAlive) {
44
- startNetworkListener();
45
- keepAlive = addNetworkListener(() => {});
46
- } else if (value === "normal") {
47
- keepAlive?.();
48
- keepAlive = undefined;
49
- if (getNetworkListenerCount() === 0) stopNetworkListener();
50
- }
51
- profile = value;
52
- listeners.forEach(listener => listener());
53
- return profile;
54
- }
55
- export function snapshotNetworkCondition(url) {
56
- if (profile === "normal" || !conditionsCanApply() || !/^https?:\/\//i.test(url)) return;
57
- return Object.freeze({
58
- profile,
59
- delayMs: NETWORK_CONDITIONS[profile].delayMs
60
- });
61
- }
62
- subscribeAccountAccess(() => {
63
- if (!hasAccountAccess()) setNetworkCondition("normal");
64
- listeners.forEach(listener => listener());
65
- });
1
+ "use strict";import{hasAccountAccess as n,subscribeAccountAccess as i}from"@buoy-gg/shared-ui";import{addNetworkListener as l,startNetworkListener as a,getNetworkListenerCount as c,stopNetworkListener as d}from"../utils/networkListener";export const NETWORK_CONDITIONS={normal:{label:"Normal",delayMs:0},offline:{label:"Offline (requests)",delayMs:0},slow:{label:"Slow (+500 ms)",delayMs:500},verySlow:{label:"Very slow (+2000 ms)",delayMs:2e3}};export const networkConditionsRuntimeId=`${Date.now()}-${Math.random().toString(36).slice(2)}`;let o="normal";let t;const r=new Set;export const conditionsCanApply=()=>typeof __DEV__!=="undefined"&&__DEV__&&n();export const getNetworkCondition=()=>o;export const subscribeNetworkConditions=e=>{r.add(e);return()=>{r.delete(e)}};export function setNetworkCondition(e){if(typeof e!=="string"||!Object.prototype.hasOwnProperty.call(NETWORK_CONDITIONS,e)){throw new Error("Choose normal, offline, slow, or verySlow.")}if(e!=="normal"&&!conditionsCanApply()){throw new Error("Network conditions require an admitted account and a development build.")}if(e===o)return o;if(e!=="normal"&&!t){a();t=l(()=>{})}else if(e==="normal"){t?.();t=void 0;if(c()===0)d()}o=e;r.forEach(s=>s());return o}export function snapshotNetworkCondition(e){if(o==="normal"||!conditionsCanApply()||!/^https?:\/\//i.test(e))return;return Object.freeze({profile:o,delayMs:NETWORK_CONDITIONS[o].delayMs})}i(()=>{if(!n())setNetworkCondition("normal");r.forEach(e=>e())});
@@ -1,38 +1 @@
1
- "use strict";
2
-
3
- export function throwIfAborted(signal) {
4
- if (!signal?.aborted) return;
5
- if (signal.reason !== undefined) throw signal.reason;
6
- const error = new Error("The request was aborted.");
7
- error.name = "AbortError";
8
- throw error;
9
- }
10
-
11
- /** Wait before dispatch, releasing the timer and listener on cancellation. */
12
- export function waitBeforeDispatch(ms, signal) {
13
- return new Promise((resolve, reject) => {
14
- try {
15
- throwIfAborted(signal);
16
- } catch (error) {
17
- reject(error);
18
- return;
19
- }
20
- const cleanup = () => signal?.removeEventListener("abort", abort);
21
- const abort = () => {
22
- clearTimeout(timer);
23
- cleanup();
24
- try {
25
- throwIfAborted(signal);
26
- } catch (error) {
27
- reject(error);
28
- }
29
- };
30
- const timer = setTimeout(() => {
31
- cleanup();
32
- resolve();
33
- }, ms);
34
- signal?.addEventListener("abort", abort, {
35
- once: true
36
- });
37
- });
38
- }
1
+ "use strict";export function throwIfAborted(e){if(!e?.aborted)return;if(e.reason!==void 0)throw e.reason;const r=new Error("The request was aborted.");r.name="AbortError";throw r}export function waitBeforeDispatch(e,r){return new Promise((u,o)=>{try{throwIfAborted(r)}catch(t){o(t);return}const n=()=>r?.removeEventListener("abort",c);const c=()=>{clearTimeout(a);n();try{throwIfAborted(r)}catch(t){o(t)}};const a=setTimeout(()=>{n();u()},e);r?.addEventListener("abort",c,{once:true})})}