react-native-debug-toolkit 0.6.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -212
  3. package/lib/commonjs/components/ClipboardTab.js +92 -0
  4. package/lib/commonjs/components/ClipboardTab.js.map +1 -0
  5. package/lib/commonjs/components/ConsoleLogTab.js +295 -0
  6. package/lib/commonjs/components/ConsoleLogTab.js.map +1 -0
  7. package/lib/commonjs/components/EnvironmentTab.js +288 -0
  8. package/lib/commonjs/components/EnvironmentTab.js.map +1 -0
  9. package/lib/commonjs/components/FloatPanelView.js +797 -0
  10. package/lib/commonjs/components/FloatPanelView.js.map +1 -0
  11. package/lib/commonjs/components/NavigationLogTab.js +131 -0
  12. package/lib/commonjs/components/NavigationLogTab.js.map +1 -0
  13. package/lib/commonjs/components/NetworkLogTab.js +575 -0
  14. package/lib/commonjs/components/NetworkLogTab.js.map +1 -0
  15. package/lib/commonjs/components/ThirdPartyLibsTab.js +97 -0
  16. package/lib/commonjs/components/ThirdPartyLibsTab.js.map +1 -0
  17. package/lib/commonjs/components/TrackLogTab.js +372 -0
  18. package/lib/commonjs/components/TrackLogTab.js.map +1 -0
  19. package/lib/commonjs/components/ZustandLogTab.js +451 -0
  20. package/lib/commonjs/components/ZustandLogTab.js.map +1 -0
  21. package/lib/commonjs/components/shared/CollapsibleSection.js +84 -0
  22. package/lib/commonjs/components/shared/CollapsibleSection.js.map +1 -0
  23. package/lib/commonjs/components/shared/CopyButton.js +64 -0
  24. package/lib/commonjs/components/shared/CopyButton.js.map +1 -0
  25. package/lib/commonjs/components/shared/JsonView.js +157 -0
  26. package/lib/commonjs/components/shared/JsonView.js.map +1 -0
  27. package/lib/commonjs/core/DebugToolkit.js +142 -0
  28. package/lib/commonjs/core/DebugToolkit.js.map +1 -0
  29. package/lib/commonjs/core/DebugToolkitProvider.js +64 -0
  30. package/lib/commonjs/core/DebugToolkitProvider.js.map +1 -0
  31. package/lib/commonjs/features/ClipboardFeature.js +17 -0
  32. package/lib/commonjs/features/ClipboardFeature.js.map +1 -0
  33. package/lib/commonjs/features/ConsoleLogFeature.js +98 -0
  34. package/lib/commonjs/features/ConsoleLogFeature.js.map +1 -0
  35. package/lib/commonjs/features/EnvironmentFeature.js +168 -0
  36. package/lib/commonjs/features/EnvironmentFeature.js.map +1 -0
  37. package/lib/commonjs/features/NavigationLogFeature.js +60 -0
  38. package/lib/commonjs/features/NavigationLogFeature.js.map +1 -0
  39. package/lib/commonjs/features/NetworkFeature.js +328 -0
  40. package/lib/commonjs/features/NetworkFeature.js.map +1 -0
  41. package/lib/commonjs/features/ThirdPartyLibsFeature.js +51 -0
  42. package/lib/commonjs/features/ThirdPartyLibsFeature.js.map +1 -0
  43. package/lib/commonjs/features/TrackFeature.js +55 -0
  44. package/lib/commonjs/features/TrackFeature.js.map +1 -0
  45. package/lib/commonjs/features/ZustandLogFeature.js +76 -0
  46. package/lib/commonjs/features/ZustandLogFeature.js.map +1 -0
  47. package/lib/commonjs/hooks/useNavigationLogger.js +78 -0
  48. package/lib/commonjs/hooks/useNavigationLogger.js.map +1 -0
  49. package/lib/commonjs/hooks/useSlideDetailAnimation.js +53 -0
  50. package/lib/commonjs/hooks/useSlideDetailAnimation.js.map +1 -0
  51. package/lib/commonjs/index.js +165 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/initialize.js +161 -0
  54. package/lib/commonjs/initialize.js.map +1 -0
  55. package/lib/commonjs/native/NativeDebugLibs.js +58 -0
  56. package/lib/commonjs/native/NativeDebugLibs.js.map +1 -0
  57. package/lib/commonjs/package.json +1 -0
  58. package/lib/commonjs/types/index.js +6 -0
  59. package/lib/commonjs/types/index.js.map +1 -0
  60. package/lib/commonjs/utils/constants.js +135 -0
  61. package/lib/commonjs/utils/constants.js.map +1 -0
  62. package/lib/commonjs/utils/copyToComputer.js +97 -0
  63. package/lib/commonjs/utils/copyToComputer.js.map +1 -0
  64. package/lib/commonjs/utils/createEventChannel.js +21 -0
  65. package/lib/commonjs/utils/createEventChannel.js.map +1 -0
  66. package/lib/commonjs/utils/createObservableStore.js +38 -0
  67. package/lib/commonjs/utils/createObservableStore.js.map +1 -0
  68. package/lib/commonjs/utils/safeStringify.js +27 -0
  69. package/lib/commonjs/utils/safeStringify.js.map +1 -0
  70. package/lib/module/components/ClipboardTab.js +86 -0
  71. package/lib/module/components/ClipboardTab.js.map +1 -0
  72. package/lib/module/components/ConsoleLogTab.js +290 -0
  73. package/lib/module/components/ConsoleLogTab.js.map +1 -0
  74. package/lib/module/components/EnvironmentTab.js +282 -0
  75. package/lib/module/components/EnvironmentTab.js.map +1 -0
  76. package/lib/module/components/FloatPanelView.js +791 -0
  77. package/lib/module/components/FloatPanelView.js.map +1 -0
  78. package/lib/module/components/NavigationLogTab.js +126 -0
  79. package/lib/module/components/NavigationLogTab.js.map +1 -0
  80. package/lib/module/components/NetworkLogTab.js +570 -0
  81. package/lib/module/components/NetworkLogTab.js.map +1 -0
  82. package/lib/module/components/ThirdPartyLibsTab.js +91 -0
  83. package/lib/module/components/ThirdPartyLibsTab.js.map +1 -0
  84. package/lib/module/components/TrackLogTab.js +367 -0
  85. package/lib/module/components/TrackLogTab.js.map +1 -0
  86. package/lib/module/components/ZustandLogTab.js +446 -0
  87. package/lib/module/components/ZustandLogTab.js.map +1 -0
  88. package/lib/module/components/shared/CollapsibleSection.js +78 -0
  89. package/lib/module/components/shared/CollapsibleSection.js.map +1 -0
  90. package/lib/module/components/shared/CopyButton.js +58 -0
  91. package/lib/module/components/shared/CopyButton.js.map +1 -0
  92. package/lib/module/components/shared/JsonView.js +152 -0
  93. package/lib/module/components/shared/JsonView.js.map +1 -0
  94. package/lib/module/core/DebugToolkit.js +137 -0
  95. package/lib/module/core/DebugToolkit.js.map +1 -0
  96. package/lib/module/core/DebugToolkitProvider.js +58 -0
  97. package/lib/module/core/DebugToolkitProvider.js.map +1 -0
  98. package/lib/module/features/ClipboardFeature.js +12 -0
  99. package/lib/module/features/ClipboardFeature.js.map +1 -0
  100. package/lib/module/features/ConsoleLogFeature.js +93 -0
  101. package/lib/module/features/ConsoleLogFeature.js.map +1 -0
  102. package/lib/module/features/EnvironmentFeature.js +164 -0
  103. package/lib/module/features/EnvironmentFeature.js.map +1 -0
  104. package/lib/module/features/NavigationLogFeature.js +54 -0
  105. package/lib/module/features/NavigationLogFeature.js.map +1 -0
  106. package/lib/module/features/NetworkFeature.js +322 -0
  107. package/lib/module/features/NetworkFeature.js.map +1 -0
  108. package/lib/module/features/ThirdPartyLibsFeature.js +46 -0
  109. package/lib/module/features/ThirdPartyLibsFeature.js.map +1 -0
  110. package/lib/module/features/TrackFeature.js +49 -0
  111. package/lib/module/features/TrackFeature.js.map +1 -0
  112. package/lib/module/features/ZustandLogFeature.js +69 -0
  113. package/lib/module/features/ZustandLogFeature.js.map +1 -0
  114. package/lib/module/hooks/useNavigationLogger.js +74 -0
  115. package/lib/module/hooks/useNavigationLogger.js.map +1 -0
  116. package/lib/module/hooks/useSlideDetailAnimation.js +50 -0
  117. package/lib/module/hooks/useSlideDetailAnimation.js.map +1 -0
  118. package/lib/module/index.js +29 -0
  119. package/lib/module/index.js.map +1 -0
  120. package/lib/module/initialize.js +156 -0
  121. package/lib/module/initialize.js.map +1 -0
  122. package/lib/module/native/NativeDebugLibs.js +54 -0
  123. package/lib/module/native/NativeDebugLibs.js.map +1 -0
  124. package/lib/module/package.json +1 -0
  125. package/lib/module/types/index.js +4 -0
  126. package/lib/module/types/index.js.map +1 -0
  127. package/lib/module/utils/constants.js +130 -0
  128. package/lib/module/utils/constants.js.map +1 -0
  129. package/lib/module/utils/copyToComputer.js +91 -0
  130. package/lib/module/utils/copyToComputer.js.map +1 -0
  131. package/lib/module/utils/createEventChannel.js +17 -0
  132. package/lib/module/utils/createEventChannel.js.map +1 -0
  133. package/lib/module/utils/createObservableStore.js +34 -0
  134. package/lib/module/utils/createObservableStore.js.map +1 -0
  135. package/lib/module/utils/safeStringify.js +23 -0
  136. package/lib/module/utils/safeStringify.js.map +1 -0
  137. package/lib/typescript/src/components/ClipboardTab.d.ts +4 -0
  138. package/lib/typescript/src/components/ClipboardTab.d.ts.map +1 -0
  139. package/lib/typescript/src/components/ConsoleLogTab.d.ts +4 -0
  140. package/lib/typescript/src/components/ConsoleLogTab.d.ts.map +1 -0
  141. package/lib/typescript/src/components/EnvironmentTab.d.ts +4 -0
  142. package/lib/typescript/src/components/EnvironmentTab.d.ts.map +1 -0
  143. package/lib/typescript/src/components/FloatPanelView.d.ts +64 -0
  144. package/lib/typescript/src/components/FloatPanelView.d.ts.map +1 -0
  145. package/lib/typescript/src/components/NavigationLogTab.d.ts +4 -0
  146. package/lib/typescript/src/components/NavigationLogTab.d.ts.map +1 -0
  147. package/lib/typescript/src/components/NetworkLogTab.d.ts +4 -0
  148. package/lib/typescript/src/components/NetworkLogTab.d.ts.map +1 -0
  149. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts +4 -0
  150. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts.map +1 -0
  151. package/lib/typescript/src/components/TrackLogTab.d.ts +4 -0
  152. package/lib/typescript/src/components/TrackLogTab.d.ts.map +1 -0
  153. package/lib/typescript/src/components/ZustandLogTab.d.ts +4 -0
  154. package/lib/typescript/src/components/ZustandLogTab.d.ts.map +1 -0
  155. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts +9 -0
  156. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts.map +1 -0
  157. package/lib/typescript/src/components/shared/CopyButton.d.ts +12 -0
  158. package/lib/typescript/src/components/shared/CopyButton.d.ts.map +1 -0
  159. package/lib/typescript/src/components/shared/JsonView.d.ts +6 -0
  160. package/lib/typescript/src/components/shared/JsonView.d.ts.map +1 -0
  161. package/lib/typescript/src/core/DebugToolkit.d.ts +27 -0
  162. package/lib/typescript/src/core/DebugToolkit.d.ts.map +1 -0
  163. package/lib/typescript/src/core/DebugToolkitProvider.d.ts +18 -0
  164. package/lib/typescript/src/core/DebugToolkitProvider.d.ts.map +1 -0
  165. package/lib/typescript/src/features/ClipboardFeature.d.ts +3 -0
  166. package/lib/typescript/src/features/ClipboardFeature.d.ts.map +1 -0
  167. package/lib/typescript/src/features/ConsoleLogFeature.d.ts +7 -0
  168. package/lib/typescript/src/features/ConsoleLogFeature.d.ts.map +1 -0
  169. package/lib/typescript/src/features/EnvironmentFeature.d.ts +8 -0
  170. package/lib/typescript/src/features/EnvironmentFeature.d.ts.map +1 -0
  171. package/lib/typescript/src/features/NavigationLogFeature.d.ts +8 -0
  172. package/lib/typescript/src/features/NavigationLogFeature.d.ts.map +1 -0
  173. package/lib/typescript/src/features/NetworkFeature.d.ts +28 -0
  174. package/lib/typescript/src/features/NetworkFeature.d.ts.map +1 -0
  175. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts +3 -0
  176. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts.map +1 -0
  177. package/lib/typescript/src/features/TrackFeature.d.ts +12 -0
  178. package/lib/typescript/src/features/TrackFeature.d.ts.map +1 -0
  179. package/lib/typescript/src/features/ZustandLogFeature.d.ts +29 -0
  180. package/lib/typescript/src/features/ZustandLogFeature.d.ts.map +1 -0
  181. package/lib/typescript/src/hooks/useNavigationLogger.d.ts +20 -0
  182. package/lib/typescript/src/hooks/useNavigationLogger.d.ts.map +1 -0
  183. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts +11 -0
  184. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts.map +1 -0
  185. package/lib/typescript/src/index.d.ts +26 -0
  186. package/lib/typescript/src/index.d.ts.map +1 -0
  187. package/lib/typescript/src/initialize.d.ts +51 -0
  188. package/lib/typescript/src/initialize.d.ts.map +1 -0
  189. package/lib/typescript/src/native/NativeDebugLibs.d.ts +11 -0
  190. package/lib/typescript/src/native/NativeDebugLibs.d.ts.map +1 -0
  191. package/lib/typescript/src/types/index.d.ts +112 -0
  192. package/lib/typescript/src/types/index.d.ts.map +1 -0
  193. package/lib/typescript/src/utils/constants.d.ts +96 -0
  194. package/lib/typescript/src/utils/constants.d.ts.map +1 -0
  195. package/lib/typescript/src/utils/copyToComputer.d.ts +30 -0
  196. package/lib/typescript/src/utils/copyToComputer.d.ts.map +1 -0
  197. package/lib/typescript/src/utils/createEventChannel.d.ts +7 -0
  198. package/lib/typescript/src/utils/createEventChannel.d.ts.map +1 -0
  199. package/lib/typescript/src/utils/createObservableStore.d.ts +9 -0
  200. package/lib/typescript/src/utils/createObservableStore.d.ts.map +1 -0
  201. package/lib/typescript/src/utils/safeStringify.d.ts +6 -0
  202. package/lib/typescript/src/utils/safeStringify.d.ts.map +1 -0
  203. package/package.json +63 -24
  204. package/src/components/ClipboardTab.tsx +81 -0
  205. package/src/components/ConsoleLogTab.tsx +209 -0
  206. package/src/components/EnvironmentTab.tsx +276 -0
  207. package/src/components/FloatPanelView.tsx +714 -0
  208. package/src/components/NavigationLogTab.tsx +66 -0
  209. package/src/components/NetworkLogTab.tsx +411 -0
  210. package/src/components/ThirdPartyLibsTab.tsx +63 -0
  211. package/src/components/TrackLogTab.tsx +245 -0
  212. package/src/components/ZustandLogTab.tsx +305 -0
  213. package/src/components/shared/CollapsibleSection.tsx +78 -0
  214. package/src/components/shared/CopyButton.tsx +68 -0
  215. package/src/components/shared/JsonView.tsx +125 -0
  216. package/src/core/DebugToolkit.tsx +174 -0
  217. package/src/core/DebugToolkitProvider.tsx +89 -0
  218. package/src/features/ClipboardFeature.ts +11 -0
  219. package/src/features/ConsoleLogFeature.ts +118 -0
  220. package/src/features/EnvironmentFeature.ts +194 -0
  221. package/src/features/NavigationLogFeature.ts +74 -0
  222. package/src/features/NetworkFeature.ts +488 -0
  223. package/src/features/ThirdPartyLibsFeature.ts +42 -0
  224. package/src/features/TrackFeature.ts +69 -0
  225. package/src/features/ZustandLogFeature.ts +127 -0
  226. package/src/hooks/useNavigationLogger.ts +107 -0
  227. package/src/hooks/useSlideDetailAnimation.ts +45 -0
  228. package/src/index.ts +52 -0
  229. package/src/initialize.ts +214 -0
  230. package/src/native/NativeDebugLibs.ts +74 -0
  231. package/src/types/index.ts +138 -0
  232. package/src/utils/constants.ts +91 -0
  233. package/src/utils/copyToComputer.ts +104 -0
  234. package/src/utils/createEventChannel.ts +22 -0
  235. package/src/utils/createObservableStore.ts +42 -0
  236. package/src/utils/safeStringify.ts +25 -0
  237. package/.cursor/rules/react-native.mdc +0 -41
  238. package/README.zh-CN.md +0 -230
  239. package/android/build.gradle +0 -34
  240. package/android/src/main/AndroidManifest.xml +0 -8
  241. package/android/src/main/java/com/reactnative/debuglibs/BuildTypeModule.java +0 -44
  242. package/android/src/main/java/com/reactnative/debuglibs/BuildTypePackage.java +0 -25
  243. package/android/src/main/java/com/reactnative/debuglibs/RNDebugLibsModule.java +0 -75
  244. package/android/src/main/java/com/reactnative/debuglibs/RNDebugLibsPackage.java +0 -28
  245. package/index.js +0 -41
  246. package/ios/BuildTypeModule.h +0 -9
  247. package/ios/BuildTypeModule.m +0 -42
  248. package/ios/RNDebugLibs.h +0 -10
  249. package/ios/RNDebugLibs.m +0 -79
  250. package/lib/DebugToolKit.js +0 -126
  251. package/lib/EnvironmentManager.ts +0 -80
  252. package/lib/NativeDebugLibs.js +0 -67
  253. package/lib/features/ConsoleLogFeature.js +0 -70
  254. package/lib/features/NavigationLogFeature.js +0 -45
  255. package/lib/features/NetworkFeature.js +0 -389
  256. package/lib/features/PerformanceFeature.js +0 -390
  257. package/lib/features/ThirdPartyLibsFeature.js +0 -63
  258. package/lib/features/TrackFeature.js +0 -94
  259. package/lib/features/ZustandLogFeature.js +0 -44
  260. package/lib/hooks/useNavigationLogger.js +0 -92
  261. package/lib/index.js +0 -114
  262. package/lib/navigation/NavigationLogger.js +0 -1
  263. package/lib/types/TrackTypes.ts +0 -92
  264. package/lib/utils/DebugConst.js +0 -67
  265. package/lib/utils/StorageUtils.js +0 -80
  266. package/lib/views/ConsoleLogDetails.js +0 -314
  267. package/lib/views/FloatPanelView.js +0 -697
  268. package/lib/views/HttpLogDetails.js +0 -648
  269. package/lib/views/NavigationLogDetails.js +0 -302
  270. package/lib/views/RestartModal.js +0 -75
  271. package/lib/views/SubViewConsoleLogs.js +0 -209
  272. package/lib/views/SubViewEnvironment.js +0 -73
  273. package/lib/views/SubViewHTTPLogs.js +0 -235
  274. package/lib/views/SubViewNavigationLogs.js +0 -199
  275. package/lib/views/SubViewPerformance.js +0 -515
  276. package/lib/views/SubViewThirdPartyLibs.js +0 -239
  277. package/lib/views/SubViewTrackLogs.js +0 -318
  278. package/lib/views/SubViewZustandLogs.js +0 -279
  279. package/lib/views/TabView.js +0 -66
  280. package/lib/views/TrackLogDetails.js +0 -481
  281. package/lib/views/ZustandLogDetails.js +0 -355
  282. package/react-native-debug-toolkit.podspec +0 -25
  283. package/react-native.config.js +0 -18
@@ -0,0 +1,209 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Text, FlatList, TouchableOpacity, StyleSheet, Animated, ScrollView } from 'react-native';
3
+ import { Colors } from '../utils/constants';
4
+ import { safeStringify } from '../utils/safeStringify';
5
+ import { CollapsibleSection } from './shared/CollapsibleSection';
6
+ import { JsonView } from './shared/JsonView';
7
+ import { CopyButton } from './shared/CopyButton';
8
+ import { fmt } from '../utils/copyToComputer';
9
+ import { useSlideDetailAnimation } from '../hooks/useSlideDetailAnimation';
10
+ import type { ConsoleLogEntry, DebugFeatureRenderProps } from '../types';
11
+
12
+ const LEVEL_COLORS: Record<string, string> = {
13
+ log: '#8E8E93',
14
+ info: '#007AFF',
15
+ warn: '#FF9500',
16
+ error: '#FF3B30',
17
+ };
18
+
19
+ const LEVEL_ICONS: Record<string, string> = {
20
+ log: '●',
21
+ info: 'ℹ',
22
+ warn: '⚠',
23
+ error: '✕',
24
+ };
25
+
26
+ export const ConsoleLogTab: React.FC<DebugFeatureRenderProps<ConsoleLogEntry>> = React.memo(({
27
+ data,
28
+ }) => {
29
+ const [selected, setSelected] = useState<ConsoleLogEntry | null>(null);
30
+ const { detailTranslateX, listTranslateX, listOpacity } = useSlideDetailAnimation(selected);
31
+
32
+ const renderItem = ({ item }: { item: ConsoleLogEntry }) => (
33
+ <TouchableOpacity style={s.card} onPress={() => setSelected(item)} activeOpacity={0.6}>
34
+ <View style={s.cardRow}>
35
+ <View style={[s.levelDot, { backgroundColor: LEVEL_COLORS[item.level] ?? '#8E8E93' }]}>
36
+ <Text style={s.levelIcon}>{LEVEL_ICONS[item.level] ?? '●'}</Text>
37
+ </View>
38
+ <View style={s.cardContent}>
39
+ <Text style={s.logMessage} numberOfLines={2}>
40
+ {item.data.map((d) => (typeof d === 'string' ? d : safeStringify(d))).join(' ')}
41
+ </Text>
42
+ <Text style={s.time}>
43
+ {new Date(item.timestamp).toLocaleTimeString()}
44
+ </Text>
45
+ </View>
46
+ </View>
47
+ </TouchableOpacity>
48
+ );
49
+
50
+ return (
51
+ <View style={s.container}>
52
+ {/* List */}
53
+ <Animated.View style={[s.listWrap, selected ? { opacity: listOpacity, transform: [{ translateX: listTranslateX }] } : null]}>
54
+ {data.length === 0 ? (
55
+ <View style={s.emptyContainer}>
56
+ <Text style={s.emptyIcon}>~</Text>
57
+ <Text style={s.empty}>No console logs</Text>
58
+ </View>
59
+ ) : (
60
+ <FlatList
61
+ data={[...data].reverse()}
62
+ renderItem={renderItem}
63
+ keyExtractor={(item) => item.id}
64
+ contentContainerStyle={s.listContent}
65
+ initialNumToRender={20}
66
+ maxToRenderPerBatch={10}
67
+ windowSize={5}
68
+ removeClippedSubviews={true}
69
+ />
70
+ )}
71
+ </Animated.View>
72
+
73
+ {/* Detail (push navigation) */}
74
+ {selected && (
75
+ <Animated.View style={[s.detailWrap, { transform: [{ translateX: detailTranslateX }] }]}>
76
+ <View style={s.detailHeader}>
77
+ <TouchableOpacity onPress={() => setSelected(null)} style={s.backBtn} activeOpacity={0.6}>
78
+ <Text style={s.backIcon}>‹</Text>
79
+ <Text style={s.backText}>Back</Text>
80
+ </TouchableOpacity>
81
+ <View style={[s.levelBadge, { backgroundColor: LEVEL_COLORS[selected.level] ?? '#8E8E93' }]}>
82
+ <Text style={s.levelBadgeText}>{selected.level.toUpperCase()}</Text>
83
+ </View>
84
+ <Text style={s.detailTime}>
85
+ {new Date(selected.timestamp).toLocaleString()}
86
+ </Text>
87
+ </View>
88
+ <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
89
+ {selected.data.map((item, index) => {
90
+ const formatted = typeof item === 'object' && item !== null
91
+ ? fmt(item)
92
+ : String(item);
93
+ return (
94
+ <CollapsibleSection
95
+ key={index}
96
+ title={typeof item === 'object' && item !== null ? `Arg ${index + 1} (object)` : `Arg ${index + 1}`}
97
+ initiallyExpanded={index === 0}
98
+ >
99
+ <View style={s.sectionWithCopy}>
100
+ <CopyButton text={formatted} label={`Console Arg ${index + 1}`} />
101
+ {typeof item === 'object' && item !== null ? (
102
+ <JsonView data={item} maxHeight={250} />
103
+ ) : (
104
+ <Text style={s.plainText} selectable>{String(item)}</Text>
105
+ )}
106
+ </View>
107
+ </CollapsibleSection>
108
+ );
109
+ })}
110
+ </ScrollView>
111
+ </Animated.View>
112
+ )}
113
+ </View>
114
+ );
115
+ });
116
+
117
+ const s = StyleSheet.create({
118
+ container: { flex: 1, backgroundColor: Colors.background },
119
+ listWrap: {
120
+ position: 'absolute',
121
+ top: 0,
122
+ left: 0,
123
+ right: 0,
124
+ bottom: 0,
125
+ },
126
+ listContent: { padding: 12 },
127
+
128
+ // Empty
129
+ emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' },
130
+ emptyIcon: { fontSize: 40, color: Colors.textLight, marginBottom: 4 },
131
+ empty: { textAlign: 'center', color: Colors.textLight, fontSize: 14 },
132
+
133
+ // Card
134
+ card: {
135
+ backgroundColor: Colors.surface,
136
+ borderRadius: 12,
137
+ marginBottom: 8,
138
+ overflow: 'hidden',
139
+ },
140
+ cardRow: { flexDirection: 'row', padding: 14, alignItems: 'flex-start' },
141
+ levelDot: {
142
+ width: 24,
143
+ height: 24,
144
+ borderRadius: 12,
145
+ alignItems: 'center',
146
+ justifyContent: 'center',
147
+ marginRight: 12,
148
+ marginTop: 1,
149
+ },
150
+ levelIcon: { color: '#FFF', fontSize: 11, fontWeight: '700' },
151
+ cardContent: { flex: 1 },
152
+ logMessage: { fontSize: 14, color: Colors.text, lineHeight: 20 },
153
+ time: { fontSize: 12, color: Colors.textSecondary, marginTop: 4 },
154
+
155
+ // Detail (in-panel navigation)
156
+ detailWrap: {
157
+ position: 'absolute',
158
+ top: 0,
159
+ left: 0,
160
+ right: 0,
161
+ bottom: 0,
162
+ backgroundColor: Colors.background,
163
+ },
164
+ detailHeader: {
165
+ flexDirection: 'row',
166
+ alignItems: 'center',
167
+ paddingHorizontal: 8,
168
+ paddingVertical: 10,
169
+ backgroundColor: Colors.surface,
170
+ borderBottomWidth: StyleSheet.hairlineWidth,
171
+ borderBottomColor: Colors.border,
172
+ gap: 6,
173
+ },
174
+ backBtn: {
175
+ flexDirection: 'row',
176
+ alignItems: 'center',
177
+ paddingHorizontal: 6,
178
+ paddingVertical: 4,
179
+ borderRadius: 8,
180
+ },
181
+ backIcon: {
182
+ fontSize: 24,
183
+ fontWeight: '300',
184
+ color: Colors.primary,
185
+ marginTop: -2,
186
+ marginRight: 2,
187
+ },
188
+ backText: {
189
+ fontSize: 16,
190
+ color: Colors.primary,
191
+ fontWeight: '500',
192
+ },
193
+ levelBadge: {
194
+ paddingHorizontal: 10,
195
+ paddingVertical: 4,
196
+ borderRadius: 6,
197
+ },
198
+ levelBadgeText: { color: '#FFF', fontSize: 12, fontWeight: '700' },
199
+ detailTime: { flex: 1, fontSize: 13, color: Colors.textSecondary, textAlign: 'right' },
200
+ detailBody: { flex: 1 },
201
+ detailBodyContent: { padding: 12 },
202
+ sectionWithCopy: { gap: 8 },
203
+ plainText: {
204
+ fontFamily: 'Courier',
205
+ fontSize: 13,
206
+ color: Colors.text,
207
+ lineHeight: 20,
208
+ },
209
+ });
@@ -0,0 +1,276 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ TouchableOpacity,
6
+ StyleSheet,
7
+ ScrollView,
8
+ } from 'react-native';
9
+ import { Colors } from '../utils/constants';
10
+ import type { DebugFeatureRenderProps, EnvironmentState } from '../types';
11
+ import type { EnvironmentFeatureAPI } from '../features/EnvironmentFeature';
12
+
13
+ const DEFAULT_COLORS: Record<string, string> = {
14
+ dev: '#34C759',
15
+ development: '#34C759',
16
+ staging: '#FF9500',
17
+ stage: '#FF9500',
18
+ production: '#FF3B30',
19
+ prod: '#FF3B30',
20
+ };
21
+
22
+ export const EnvironmentTab: React.FC<DebugFeatureRenderProps<EnvironmentState>> = ({
23
+ data,
24
+ feature,
25
+ }) => {
26
+ const state = data[0];
27
+ if (!state || state.environments.length === 0) {
28
+ return (
29
+ <View style={styles.container}>
30
+ <View style={styles.emptyContainer}>
31
+ <Text style={styles.emptyIcon}>⚙</Text>
32
+ <Text style={styles.emptyTitle}>No Environments</Text>
33
+ <Text style={styles.emptyDesc}>
34
+ Call{'\n'}
35
+ <Text style={styles.code}>registerEnvironments([...])</Text>{'\n'}
36
+ to configure environments.
37
+ </Text>
38
+ </View>
39
+ </View>
40
+ );
41
+ }
42
+
43
+ const { environments, currentEnvironmentId } = state;
44
+ const envFeature = feature as unknown as EnvironmentFeatureAPI;
45
+
46
+ const handleSelect = (envId: string) => {
47
+ const nextId = currentEnvironmentId === envId ? null : envId;
48
+ envFeature.switchEnvironment?.(nextId);
49
+ };
50
+
51
+ const activeEnv = environments.find((e) => e.id === currentEnvironmentId);
52
+
53
+ return (
54
+ <View style={styles.container}>
55
+ <View style={styles.headerSection}>
56
+ <Text style={styles.sectionTitle}>Switch Environment</Text>
57
+ <Text style={styles.sectionDesc}>
58
+ Rewrite API host in outgoing requests. Only registered hosts are affected.
59
+ </Text>
60
+ </View>
61
+
62
+ <ScrollView style={styles.list} contentContainerStyle={styles.listContent}>
63
+ <View style={styles.groupedCard}>
64
+ {environments.map((env, index) => {
65
+ const isActive = currentEnvironmentId === env.id;
66
+ const color = env.color || DEFAULT_COLORS[env.id.toLowerCase()] || Colors.primary;
67
+
68
+ return (
69
+ <TouchableOpacity
70
+ key={env.id}
71
+ style={[
72
+ styles.envItem,
73
+ isActive && styles.envItemActive,
74
+ index < environments.length - 1 && styles.envItemSeparator,
75
+ ]}
76
+ onPress={() => handleSelect(env.id)}
77
+ activeOpacity={0.5}
78
+ >
79
+ <View style={styles.envRow}>
80
+ <View style={[styles.colorDot, { backgroundColor: color }]} />
81
+ <View style={styles.envInfo}>
82
+ <Text style={styles.envLabel}>{env.label}</Text>
83
+ <Text style={styles.envHost} numberOfLines={1}>
84
+ {env.host}
85
+ </Text>
86
+ </View>
87
+ {isActive && (
88
+ <Text style={styles.checkmark}>✓</Text>
89
+ )}
90
+ </View>
91
+ </TouchableOpacity>
92
+ );
93
+ })}
94
+ </View>
95
+ </ScrollView>
96
+
97
+ {activeEnv ? (
98
+ <View style={styles.footer}>
99
+ <View style={styles.footerInfo}>
100
+ <View style={styles.footerActiveIndicator}>
101
+ <View style={[styles.footerDot, { backgroundColor: activeEnv.color || DEFAULT_COLORS[activeEnv.id.toLowerCase()] || Colors.primary }]} />
102
+ <Text style={styles.footerLabel}>Active</Text>
103
+ </View>
104
+ <Text style={styles.footerValue}>{activeEnv.label}</Text>
105
+ </View>
106
+ <TouchableOpacity
107
+ style={styles.resetButton}
108
+ onPress={() => envFeature.switchEnvironment?.(null)}
109
+ activeOpacity={0.7}
110
+ >
111
+ <Text style={styles.resetButtonText}>Reset</Text>
112
+ </TouchableOpacity>
113
+ </View>
114
+ ) : null}
115
+ </View>
116
+ );
117
+ };
118
+
119
+ const styles = StyleSheet.create({
120
+ container: {
121
+ flex: 1,
122
+ backgroundColor: Colors.background,
123
+ },
124
+
125
+ // Empty state
126
+ emptyContainer: {
127
+ flex: 1,
128
+ alignItems: 'center',
129
+ justifyContent: 'center',
130
+ paddingHorizontal: 30,
131
+ },
132
+ emptyIcon: {
133
+ fontSize: 36,
134
+ color: Colors.textLight,
135
+ marginBottom: 8,
136
+ },
137
+ emptyTitle: {
138
+ fontSize: 20,
139
+ fontWeight: '700',
140
+ color: Colors.text,
141
+ marginBottom: 8,
142
+ },
143
+ emptyDesc: {
144
+ fontSize: 14,
145
+ color: Colors.textSecondary,
146
+ textAlign: 'center',
147
+ lineHeight: 22,
148
+ },
149
+ code: {
150
+ fontFamily: 'monospace',
151
+ fontWeight: '600',
152
+ color: Colors.primary,
153
+ },
154
+
155
+ // Header
156
+ headerSection: {
157
+ paddingHorizontal: 16,
158
+ paddingTop: 20,
159
+ paddingBottom: 14,
160
+ },
161
+ sectionTitle: {
162
+ fontSize: 13,
163
+ fontWeight: '600',
164
+ color: Colors.textSecondary,
165
+ textTransform: 'uppercase',
166
+ marginBottom: 6,
167
+ },
168
+ sectionDesc: {
169
+ fontSize: 14,
170
+ color: Colors.textSecondary,
171
+ lineHeight: 20,
172
+ },
173
+
174
+ // Grouped list (iOS Settings style)
175
+ list: {
176
+ flex: 1,
177
+ },
178
+ listContent: {
179
+ paddingHorizontal: 16,
180
+ paddingBottom: 16,
181
+ },
182
+ groupedCard: {
183
+ backgroundColor: Colors.surface,
184
+ borderRadius: 12,
185
+ overflow: 'hidden',
186
+ },
187
+ envItem: {
188
+ paddingHorizontal: 16,
189
+ paddingVertical: 14,
190
+ },
191
+ envItemActive: {
192
+ backgroundColor: 'rgba(0,122,255,0.03)',
193
+ },
194
+ envItemSeparator: {
195
+ borderBottomWidth: StyleSheet.hairlineWidth,
196
+ borderBottomColor: Colors.border,
197
+ marginLeft: 48,
198
+ },
199
+ envRow: {
200
+ flexDirection: 'row',
201
+ alignItems: 'center',
202
+ },
203
+ colorDot: {
204
+ width: 10,
205
+ height: 10,
206
+ borderRadius: 5,
207
+ marginRight: 14,
208
+ },
209
+ envInfo: {
210
+ flex: 1,
211
+ },
212
+ envLabel: {
213
+ fontSize: 16,
214
+ fontWeight: '500',
215
+ color: Colors.text,
216
+ },
217
+ envHost: {
218
+ fontSize: 13,
219
+ color: Colors.textSecondary,
220
+ marginTop: 2,
221
+ },
222
+ checkmark: {
223
+ fontSize: 18,
224
+ fontWeight: '600',
225
+ color: Colors.primary,
226
+ marginLeft: 8,
227
+ },
228
+
229
+ // Footer
230
+ footer: {
231
+ flexDirection: 'row',
232
+ alignItems: 'center',
233
+ justifyContent: 'space-between',
234
+ paddingHorizontal: 16,
235
+ paddingVertical: 14,
236
+ backgroundColor: Colors.surface,
237
+ borderTopWidth: StyleSheet.hairlineWidth,
238
+ borderTopColor: Colors.border,
239
+ },
240
+ footerInfo: {
241
+ flex: 1,
242
+ },
243
+ footerActiveIndicator: {
244
+ flexDirection: 'row',
245
+ alignItems: 'center',
246
+ gap: 6,
247
+ marginBottom: 2,
248
+ },
249
+ footerDot: {
250
+ width: 8,
251
+ height: 8,
252
+ borderRadius: 4,
253
+ },
254
+ footerLabel: {
255
+ fontSize: 11,
256
+ color: Colors.textSecondary,
257
+ fontWeight: '600',
258
+ textTransform: 'uppercase',
259
+ },
260
+ footerValue: {
261
+ fontSize: 17,
262
+ fontWeight: '600',
263
+ color: Colors.text,
264
+ },
265
+ resetButton: {
266
+ backgroundColor: 'rgba(255,59,48,0.08)',
267
+ paddingHorizontal: 20,
268
+ paddingVertical: 10,
269
+ borderRadius: 10,
270
+ },
271
+ resetButtonText: {
272
+ color: Colors.error,
273
+ fontSize: 15,
274
+ fontWeight: '600',
275
+ },
276
+ });