react-native-debug-toolkit 2.0.0 → 2.1.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 (228) hide show
  1. package/README.md +72 -72
  2. package/README.zh-CN.md +209 -0
  3. package/lib/commonjs/components/ClipboardTab.js +15 -16
  4. package/lib/commonjs/components/ClipboardTab.js.map +1 -1
  5. package/lib/commonjs/components/ConsoleLogTab.js +69 -202
  6. package/lib/commonjs/components/ConsoleLogTab.js.map +1 -1
  7. package/lib/commonjs/components/DebugPanel.js +230 -0
  8. package/lib/commonjs/components/DebugPanel.js.map +1 -0
  9. package/lib/commonjs/components/DebugView.js +66 -0
  10. package/lib/commonjs/components/DebugView.js.map +1 -0
  11. package/lib/commonjs/components/EnvironmentTab.js +22 -23
  12. package/lib/commonjs/components/EnvironmentTab.js.map +1 -1
  13. package/lib/commonjs/components/FeatureTabBar.js +182 -0
  14. package/lib/commonjs/components/FeatureTabBar.js.map +1 -0
  15. package/lib/commonjs/components/FloatIcon.js +187 -0
  16. package/lib/commonjs/components/FloatIcon.js.map +1 -0
  17. package/lib/commonjs/components/FloatPanelView.js +140 -723
  18. package/lib/commonjs/components/FloatPanelView.js.map +1 -1
  19. package/lib/commonjs/components/NavigationLogTab.js +8 -8
  20. package/lib/commonjs/components/NavigationLogTab.js.map +1 -1
  21. package/lib/commonjs/components/NetworkLogTab.js +179 -350
  22. package/lib/commonjs/components/NetworkLogTab.js.map +1 -1
  23. package/lib/commonjs/components/ThirdPartyLibsTab.js +8 -8
  24. package/lib/commonjs/components/ThirdPartyLibsTab.js.map +1 -1
  25. package/lib/commonjs/components/TrackLogTab.js +106 -248
  26. package/lib/commonjs/components/TrackLogTab.js.map +1 -1
  27. package/lib/commonjs/components/ZustandLogTab.js +148 -288
  28. package/lib/commonjs/components/ZustandLogTab.js.map +1 -1
  29. package/lib/commonjs/components/shared/CollapsibleSection.js +4 -4
  30. package/lib/commonjs/components/shared/CollapsibleSection.js.map +1 -1
  31. package/lib/commonjs/components/shared/CopyButton.js +3 -3
  32. package/lib/commonjs/components/shared/CopyButton.js.map +1 -1
  33. package/lib/commonjs/components/shared/LogListScreen.js +174 -0
  34. package/lib/commonjs/components/shared/LogListScreen.js.map +1 -0
  35. package/lib/commonjs/core/DebugToolkit.js +92 -112
  36. package/lib/commonjs/core/DebugToolkit.js.map +1 -1
  37. package/lib/commonjs/core/DebugToolkitProvider.js +30 -28
  38. package/lib/commonjs/core/DebugToolkitProvider.js.map +1 -1
  39. package/lib/commonjs/features/ClipboardFeature.js +6 -2
  40. package/lib/commonjs/features/ClipboardFeature.js.map +1 -1
  41. package/lib/commonjs/features/ConsoleLogFeature.js +66 -49
  42. package/lib/commonjs/features/ConsoleLogFeature.js.map +1 -1
  43. package/lib/commonjs/features/EnvironmentFeature.js +5 -13
  44. package/lib/commonjs/features/EnvironmentFeature.js.map +1 -1
  45. package/lib/commonjs/features/NavigationLogFeature.js +17 -38
  46. package/lib/commonjs/features/NavigationLogFeature.js.map +1 -1
  47. package/lib/commonjs/features/NetworkFeature.js +35 -256
  48. package/lib/commonjs/features/NetworkFeature.js.map +1 -1
  49. package/lib/commonjs/features/TrackFeature.js +17 -38
  50. package/lib/commonjs/features/TrackFeature.js.map +1 -1
  51. package/lib/commonjs/features/ZustandLogFeature.js +21 -38
  52. package/lib/commonjs/features/ZustandLogFeature.js.map +1 -1
  53. package/lib/commonjs/hooks/useNavigationLogger.js.map +1 -1
  54. package/lib/commonjs/index.js +7 -20
  55. package/lib/commonjs/index.js.map +1 -1
  56. package/lib/commonjs/initialize.js +19 -96
  57. package/lib/commonjs/initialize.js.map +1 -1
  58. package/lib/commonjs/interceptors/networkInterceptor.js +466 -0
  59. package/lib/commonjs/interceptors/networkInterceptor.js.map +1 -0
  60. package/lib/commonjs/utils/colors.js +48 -0
  61. package/lib/commonjs/utils/colors.js.map +1 -0
  62. package/lib/commonjs/utils/createChannelFeature.js +48 -0
  63. package/lib/commonjs/utils/createChannelFeature.js.map +1 -0
  64. package/lib/commonjs/utils/layout.js +8 -0
  65. package/lib/commonjs/utils/layout.js.map +1 -0
  66. package/lib/commonjs/utils/urlRewriterRegistry.js +14 -0
  67. package/lib/commonjs/utils/urlRewriterRegistry.js.map +1 -0
  68. package/lib/module/components/ClipboardTab.js +8 -8
  69. package/lib/module/components/ClipboardTab.js.map +1 -1
  70. package/lib/module/components/ConsoleLogTab.js +66 -199
  71. package/lib/module/components/ConsoleLogTab.js.map +1 -1
  72. package/lib/module/components/DebugPanel.js +225 -0
  73. package/lib/module/components/DebugPanel.js.map +1 -0
  74. package/lib/module/components/DebugView.js +61 -0
  75. package/lib/module/components/DebugView.js.map +1 -0
  76. package/lib/module/components/EnvironmentTab.js +3 -3
  77. package/lib/module/components/EnvironmentTab.js.map +1 -1
  78. package/lib/module/components/FeatureTabBar.js +177 -0
  79. package/lib/module/components/FeatureTabBar.js.map +1 -0
  80. package/lib/module/components/FloatIcon.js +182 -0
  81. package/lib/module/components/FloatIcon.js.map +1 -0
  82. package/lib/module/components/FloatPanelView.js +141 -723
  83. package/lib/module/components/FloatPanelView.js.map +1 -1
  84. package/lib/module/components/NavigationLogTab.js +1 -1
  85. package/lib/module/components/NavigationLogTab.js.map +1 -1
  86. package/lib/module/components/NetworkLogTab.js +167 -338
  87. package/lib/module/components/NetworkLogTab.js.map +1 -1
  88. package/lib/module/components/ThirdPartyLibsTab.js +1 -1
  89. package/lib/module/components/ThirdPartyLibsTab.js.map +1 -1
  90. package/lib/module/components/TrackLogTab.js +94 -236
  91. package/lib/module/components/TrackLogTab.js.map +1 -1
  92. package/lib/module/components/ZustandLogTab.js +136 -276
  93. package/lib/module/components/ZustandLogTab.js.map +1 -1
  94. package/lib/module/components/shared/CollapsibleSection.js +1 -1
  95. package/lib/module/components/shared/CollapsibleSection.js.map +1 -1
  96. package/lib/module/components/shared/CopyButton.js +1 -1
  97. package/lib/module/components/shared/CopyButton.js.map +1 -1
  98. package/lib/module/components/shared/LogListScreen.js +169 -0
  99. package/lib/module/components/shared/LogListScreen.js.map +1 -0
  100. package/lib/module/core/DebugToolkit.js +92 -111
  101. package/lib/module/core/DebugToolkit.js.map +1 -1
  102. package/lib/module/core/DebugToolkitProvider.js +31 -29
  103. package/lib/module/core/DebugToolkitProvider.js.map +1 -1
  104. package/lib/module/features/ClipboardFeature.js +6 -2
  105. package/lib/module/features/ClipboardFeature.js.map +1 -1
  106. package/lib/module/features/ConsoleLogFeature.js +65 -49
  107. package/lib/module/features/ConsoleLogFeature.js.map +1 -1
  108. package/lib/module/features/EnvironmentFeature.js +5 -13
  109. package/lib/module/features/EnvironmentFeature.js.map +1 -1
  110. package/lib/module/features/NavigationLogFeature.js +16 -38
  111. package/lib/module/features/NavigationLogFeature.js.map +1 -1
  112. package/lib/module/features/NetworkFeature.js +34 -255
  113. package/lib/module/features/NetworkFeature.js.map +1 -1
  114. package/lib/module/features/TrackFeature.js +16 -38
  115. package/lib/module/features/TrackFeature.js.map +1 -1
  116. package/lib/module/features/ZustandLogFeature.js +22 -38
  117. package/lib/module/features/ZustandLogFeature.js.map +1 -1
  118. package/lib/module/hooks/useNavigationLogger.js.map +1 -1
  119. package/lib/module/index.js +2 -3
  120. package/lib/module/index.js.map +1 -1
  121. package/lib/module/initialize.js +19 -95
  122. package/lib/module/initialize.js.map +1 -1
  123. package/lib/module/interceptors/networkInterceptor.js +460 -0
  124. package/lib/module/interceptors/networkInterceptor.js.map +1 -0
  125. package/lib/module/utils/colors.js +43 -0
  126. package/lib/module/utils/colors.js.map +1 -0
  127. package/lib/module/utils/createChannelFeature.js +44 -0
  128. package/lib/module/utils/createChannelFeature.js.map +1 -0
  129. package/lib/module/utils/layout.js +4 -0
  130. package/lib/module/utils/layout.js.map +1 -0
  131. package/lib/module/utils/urlRewriterRegistry.js +10 -0
  132. package/lib/module/utils/urlRewriterRegistry.js.map +1 -0
  133. package/lib/typescript/src/components/ClipboardTab.d.ts.map +1 -1
  134. package/lib/typescript/src/components/ConsoleLogTab.d.ts.map +1 -1
  135. package/lib/typescript/src/components/DebugPanel.d.ts +9 -0
  136. package/lib/typescript/src/components/DebugPanel.d.ts.map +1 -0
  137. package/lib/typescript/src/components/DebugView.d.ts +19 -0
  138. package/lib/typescript/src/components/DebugView.d.ts.map +1 -0
  139. package/lib/typescript/src/components/EnvironmentTab.d.ts.map +1 -1
  140. package/lib/typescript/src/components/FeatureTabBar.d.ts +13 -0
  141. package/lib/typescript/src/components/FeatureTabBar.d.ts.map +1 -0
  142. package/lib/typescript/src/components/FloatIcon.d.ts +12 -0
  143. package/lib/typescript/src/components/FloatIcon.d.ts.map +1 -0
  144. package/lib/typescript/src/components/FloatPanelView.d.ts +4 -59
  145. package/lib/typescript/src/components/FloatPanelView.d.ts.map +1 -1
  146. package/lib/typescript/src/components/NetworkLogTab.d.ts.map +1 -1
  147. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts.map +1 -1
  148. package/lib/typescript/src/components/TrackLogTab.d.ts.map +1 -1
  149. package/lib/typescript/src/components/ZustandLogTab.d.ts.map +1 -1
  150. package/lib/typescript/src/components/shared/LogListScreen.d.ts +21 -0
  151. package/lib/typescript/src/components/shared/LogListScreen.d.ts.map +1 -0
  152. package/lib/typescript/src/core/DebugToolkit.d.ts +11 -18
  153. package/lib/typescript/src/core/DebugToolkit.d.ts.map +1 -1
  154. package/lib/typescript/src/core/DebugToolkitProvider.d.ts +2 -5
  155. package/lib/typescript/src/core/DebugToolkitProvider.d.ts.map +1 -1
  156. package/lib/typescript/src/features/ClipboardFeature.d.ts +4 -0
  157. package/lib/typescript/src/features/ClipboardFeature.d.ts.map +1 -1
  158. package/lib/typescript/src/features/ConsoleLogFeature.d.ts +2 -0
  159. package/lib/typescript/src/features/ConsoleLogFeature.d.ts.map +1 -1
  160. package/lib/typescript/src/features/EnvironmentFeature.d.ts.map +1 -1
  161. package/lib/typescript/src/features/NavigationLogFeature.d.ts +2 -0
  162. package/lib/typescript/src/features/NavigationLogFeature.d.ts.map +1 -1
  163. package/lib/typescript/src/features/NetworkFeature.d.ts +7 -20
  164. package/lib/typescript/src/features/NetworkFeature.d.ts.map +1 -1
  165. package/lib/typescript/src/features/TrackFeature.d.ts +2 -0
  166. package/lib/typescript/src/features/TrackFeature.d.ts.map +1 -1
  167. package/lib/typescript/src/features/ZustandLogFeature.d.ts +2 -0
  168. package/lib/typescript/src/features/ZustandLogFeature.d.ts.map +1 -1
  169. package/lib/typescript/src/hooks/useNavigationLogger.d.ts +1 -8
  170. package/lib/typescript/src/hooks/useNavigationLogger.d.ts.map +1 -1
  171. package/lib/typescript/src/index.d.ts +5 -5
  172. package/lib/typescript/src/index.d.ts.map +1 -1
  173. package/lib/typescript/src/initialize.d.ts +3 -22
  174. package/lib/typescript/src/initialize.d.ts.map +1 -1
  175. package/lib/typescript/src/interceptors/networkInterceptor.d.ts +18 -0
  176. package/lib/typescript/src/interceptors/networkInterceptor.d.ts.map +1 -0
  177. package/lib/typescript/src/types/index.d.ts +26 -29
  178. package/lib/typescript/src/types/index.d.ts.map +1 -1
  179. package/lib/typescript/src/utils/colors.d.ts +21 -0
  180. package/lib/typescript/src/utils/colors.d.ts.map +1 -0
  181. package/lib/typescript/src/utils/createChannelFeature.d.ts +18 -0
  182. package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -0
  183. package/lib/typescript/src/utils/layout.d.ts +2 -0
  184. package/lib/typescript/src/utils/layout.d.ts.map +1 -0
  185. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts +7 -0
  186. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts.map +1 -0
  187. package/package.json +5 -1
  188. package/src/components/ClipboardTab.tsx +8 -8
  189. package/src/components/ConsoleLogTab.tsx +49 -163
  190. package/src/components/DebugPanel.tsx +215 -0
  191. package/src/components/DebugView.tsx +80 -0
  192. package/src/components/EnvironmentTab.tsx +3 -3
  193. package/src/components/FeatureTabBar.tsx +204 -0
  194. package/src/components/FloatIcon.tsx +171 -0
  195. package/src/components/FloatPanelView.tsx +135 -647
  196. package/src/components/NavigationLogTab.tsx +1 -1
  197. package/src/components/NetworkLogTab.tsx +128 -269
  198. package/src/components/ThirdPartyLibsTab.tsx +3 -3
  199. package/src/components/TrackLogTab.tsx +53 -188
  200. package/src/components/ZustandLogTab.tsx +79 -181
  201. package/src/components/shared/CollapsibleSection.tsx +1 -1
  202. package/src/components/shared/CopyButton.tsx +1 -1
  203. package/src/components/shared/LogListScreen.tsx +164 -0
  204. package/src/core/DebugToolkit.tsx +114 -138
  205. package/src/core/DebugToolkitProvider.tsx +32 -38
  206. package/src/features/ClipboardFeature.ts +6 -2
  207. package/src/features/ConsoleLogFeature.ts +66 -68
  208. package/src/features/EnvironmentFeature.ts +5 -13
  209. package/src/features/NavigationLogFeature.ts +12 -42
  210. package/src/features/NetworkFeature.ts +43 -405
  211. package/src/features/TrackFeature.ts +14 -49
  212. package/src/features/ZustandLogFeature.ts +16 -42
  213. package/src/hooks/useNavigationLogger.ts +1 -6
  214. package/src/index.ts +5 -9
  215. package/src/initialize.ts +28 -120
  216. package/src/interceptors/networkInterceptor.ts +646 -0
  217. package/src/types/index.ts +25 -36
  218. package/src/utils/colors.ts +38 -0
  219. package/src/utils/createChannelFeature.ts +55 -0
  220. package/src/utils/layout.ts +1 -0
  221. package/src/utils/urlRewriterRegistry.ts +10 -0
  222. package/lib/commonjs/utils/constants.js +0 -135
  223. package/lib/commonjs/utils/constants.js.map +0 -1
  224. package/lib/module/utils/constants.js +0 -130
  225. package/lib/module/utils/constants.js.map +0 -1
  226. package/lib/typescript/src/utils/constants.d.ts +0 -96
  227. package/lib/typescript/src/utils/constants.d.ts.map +0 -1
  228. package/src/utils/constants.ts +0 -91
@@ -1,25 +1,20 @@
1
- import React, { useState } from 'react';
2
- import { View, Text, FlatList, TouchableOpacity, StyleSheet, Animated, ScrollView } from 'react-native';
3
- import { Colors } from '../utils/constants';
1
+ import React from 'react';
2
+ import { View, Text, StyleSheet, ScrollView } from 'react-native';
3
+ import { Colors } from '../utils/colors';
4
4
  import { safeStringify } from '../utils/safeStringify';
5
5
  import { CollapsibleSection } from './shared/CollapsibleSection';
6
6
  import { JsonView } from './shared/JsonView';
7
7
  import { CopyButton } from './shared/CopyButton';
8
- import { useSlideDetailAnimation } from '../hooks/useSlideDetailAnimation';
8
+ import { LogListScreen } from './shared/LogListScreen';
9
9
  import type { DebugFeatureRenderProps, TrackLogEntry } from '../types';
10
10
 
11
- export const TrackLogTab: React.FC<DebugFeatureRenderProps<TrackLogEntry>> = React.memo(({
12
- data,
13
- }) => {
14
- const [selected, setSelected] = useState<TrackLogEntry | null>(null);
15
- const { detailTranslateX, listTranslateX, listOpacity } = useSlideDetailAnimation(selected);
16
-
17
- const renderItem = ({ item }: { item: TrackLogEntry }) => (
18
- <TouchableOpacity style={s.card} onPress={() => setSelected(item)} activeOpacity={0.6}>
11
+ export const TrackLogTab: React.FC<DebugFeatureRenderProps<TrackLogEntry>> = React.memo(({ data }) => (
12
+ <LogListScreen
13
+ data={data}
14
+ emptyText="No track events"
15
+ renderRow={(item) => (
19
16
  <View style={s.cardRow}>
20
- <View style={s.eventIcon}>
21
- <Text style={s.eventIconText}>●</Text>
22
- </View>
17
+ <View style={s.eventIcon}><Text style={s.eventIconText}>●</Text></View>
23
18
  <View style={s.cardContent}>
24
19
  <View style={s.cardHeader}>
25
20
  <Text style={s.eventName}>{item.eventName}</Text>
@@ -39,125 +34,54 @@ export const TrackLogTab: React.FC<DebugFeatureRenderProps<TrackLogEntry>> = Rea
39
34
  </View>
40
35
  </View>
41
36
  </View>
42
- </TouchableOpacity>
43
- );
44
-
45
- const extraProps = selected
46
- ? Object.entries(selected).filter(
37
+ )}
38
+ renderDetailHeader={(item) => (
39
+ <View style={s.eventBadge}><Text style={s.eventBadgeText}>{item.eventName}</Text></View>
40
+ )}
41
+ renderDetailBody={(item) => {
42
+ const extraProps = Object.entries(item).filter(
47
43
  ([k, v]) => k !== 'id' && k !== 'eventName' && k !== 'timestamp' && v !== undefined && v !== null,
48
- )
49
- : [];
50
-
51
- return (
52
- <View style={s.container}>
53
- {/* List */}
54
- <Animated.View style={[s.listWrap, selected ? { opacity: listOpacity, transform: [{ translateX: listTranslateX }] } : null]}>
55
- {data.length === 0 ? (
56
- <View style={s.emptyContainer}>
57
- <Text style={s.emptyIcon}>~</Text>
58
- <Text style={s.empty}>No track events</Text>
59
- </View>
60
- ) : (
61
- <FlatList
62
- data={[...data].reverse()}
63
- renderItem={renderItem}
64
- keyExtractor={(item) => item.id}
65
- contentContainerStyle={s.listContent}
66
- initialNumToRender={20}
67
- maxToRenderPerBatch={10}
68
- windowSize={5}
69
- removeClippedSubviews={true}
70
- />
71
- )}
72
- </Animated.View>
73
-
74
- {/* Detail (push navigation) */}
75
- {selected && (
76
- <Animated.View style={[s.detailOverlay, { transform: [{ translateX: detailTranslateX }] }]}>
77
- <View style={s.detailWrap}>
78
- <View style={s.detailHeader}>
79
- <TouchableOpacity onPress={() => setSelected(null)} style={s.backBtn} activeOpacity={0.6}>
80
- <Text style={s.backIcon}>‹</Text>
81
- <Text style={s.backText}>Back</Text>
82
- </TouchableOpacity>
83
- <View style={s.eventBadge}>
84
- <Text style={s.eventBadgeText}>{selected.eventName}</Text>
85
- </View>
86
- </View>
87
- <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
88
- {/* Properties */}
89
- <CollapsibleSection title="Properties" initiallyExpanded>
90
- <View style={s.sectionWithCopy}>
91
- <CopyButton text={safeStringify(Object.fromEntries(extraProps), 2)} label="Track Properties" />
92
- <View style={s.propsGrid}>
93
- {extraProps.map(([key, value]) => (
94
- <View key={key} style={s.propRow}>
95
- <Text style={s.propKey}>{key}</Text>
96
- <Text style={s.propValue} selectable>
97
- {typeof value === 'object' ? safeStringify(value) : String(value ?? '')}
98
- </Text>
99
- </View>
100
- ))}
44
+ );
45
+ return (
46
+ <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
47
+ <CollapsibleSection title="Properties" initiallyExpanded>
48
+ <View style={s.sectionWithCopy}>
49
+ <CopyButton text={safeStringify(Object.fromEntries(extraProps), 2)} label="Track Properties" />
50
+ <View style={s.propsGrid}>
51
+ {extraProps.map(([key, value]) => (
52
+ <View key={key} style={s.propRow}>
53
+ <Text style={s.propKey}>{key}</Text>
54
+ <Text style={s.propValue} selectable>
55
+ {typeof value === 'object' ? safeStringify(value) : String(value ?? '')}
56
+ </Text>
101
57
  </View>
102
- </View>
103
- </CollapsibleSection>
104
-
105
- {/* Full JSON */}
106
- <CollapsibleSection title="Full Event Data">
107
- <View style={s.sectionWithCopy}>
108
- <CopyButton text={safeStringify(selected, 2)} label="Track Event" />
109
- <JsonView data={selected} maxHeight={300} />
110
- </View>
111
- </CollapsibleSection>
112
-
113
- {/* Timing */}
114
- <View style={s.timingCard}>
115
- <Text style={s.timingLabel}>Time</Text>
116
- <Text style={s.timingValue}>
117
- {new Date(selected.timestamp).toLocaleString()}
118
- </Text>
58
+ ))}
119
59
  </View>
120
- </ScrollView>
60
+ </View>
61
+ </CollapsibleSection>
62
+ <CollapsibleSection title="Full Event Data">
63
+ <View style={s.sectionWithCopy}>
64
+ <CopyButton text={safeStringify(item, 2)} label="Track Event" />
65
+ <JsonView data={item} maxHeight={300} />
66
+ </View>
67
+ </CollapsibleSection>
68
+ <View style={s.timingCard}>
69
+ <Text style={s.timingLabel}>Time</Text>
70
+ <Text style={s.timingValue}>{new Date(item.timestamp).toLocaleString()}</Text>
121
71
  </View>
122
- </Animated.View>
123
- )}
124
- </View>
125
- );
126
- });
72
+ </ScrollView>
73
+ );
74
+ }}
75
+ />
76
+ ));
127
77
 
128
78
  const s = StyleSheet.create({
129
- container: { flex: 1, backgroundColor: Colors.background },
130
- listWrap: {
131
- position: 'absolute',
132
- top: 0,
133
- left: 0,
134
- right: 0,
135
- bottom: 0,
136
- },
137
- listContent: { padding: 12 },
138
-
139
- // Empty
140
- emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' },
141
- emptyIcon: { fontSize: 40, color: Colors.textLight, marginBottom: 4 },
142
- empty: { textAlign: 'center', color: Colors.textLight, fontSize: 14 },
143
-
144
- // Card
145
- card: {
146
- backgroundColor: Colors.surface,
147
- borderRadius: 12,
148
- marginBottom: 8,
149
- overflow: 'hidden',
150
- },
151
79
  cardRow: { flexDirection: 'row', padding: 14, alignItems: 'flex-start' },
152
80
  eventIcon: {
153
- width: 28,
154
- height: 28,
155
- borderRadius: 8,
81
+ width: 28, height: 28, borderRadius: 8,
156
82
  backgroundColor: 'rgba(175,82,222,0.1)',
157
- alignItems: 'center',
158
- justifyContent: 'center',
159
- marginRight: 12,
160
- marginTop: 1,
83
+ alignItems: 'center', justifyContent: 'center',
84
+ marginRight: 12, marginTop: 1,
161
85
  },
162
86
  eventIconText: { color: Colors.purple, fontSize: 10 },
163
87
  cardContent: { flex: 1 },
@@ -165,80 +89,21 @@ const s = StyleSheet.create({
165
89
  eventName: { fontSize: 15, fontWeight: '600', color: Colors.text },
166
90
  time: { fontSize: 12, color: Colors.textSecondary },
167
91
  previewRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 4 },
168
- previewChip: {
169
- backgroundColor: Colors.background,
170
- borderRadius: 6,
171
- paddingHorizontal: 8,
172
- paddingVertical: 3,
173
- },
92
+ previewChip: { backgroundColor: Colors.background, borderRadius: 6, paddingHorizontal: 8, paddingVertical: 3 },
174
93
  previewText: { fontSize: 12, color: Colors.textSecondary, lineHeight: 16 },
175
94
  previewKey: { fontWeight: '600', color: Colors.text },
176
-
177
- // Detail (push navigation)
178
- detailOverlay: {
179
- position: 'absolute',
180
- top: 0,
181
- left: 0,
182
- right: 0,
183
- bottom: 0,
184
- backgroundColor: Colors.background,
185
- },
186
- detailWrap: { flex: 1, backgroundColor: Colors.background },
187
- detailHeader: {
188
- flexDirection: 'row',
189
- alignItems: 'center',
190
- paddingHorizontal: 8,
191
- paddingVertical: 10,
192
- backgroundColor: Colors.surface,
193
- borderBottomWidth: StyleSheet.hairlineWidth,
194
- borderBottomColor: Colors.border,
195
- gap: 8,
196
- },
197
- backBtn: {
198
- flexDirection: 'row',
199
- alignItems: 'center',
200
- paddingHorizontal: 6,
201
- paddingVertical: 4,
202
- borderRadius: 8,
203
- },
204
- backIcon: {
205
- fontSize: 24,
206
- fontWeight: '300',
207
- color: Colors.primary,
208
- marginTop: -2,
209
- marginRight: 2,
210
- },
211
- backText: {
212
- fontSize: 16,
213
- color: Colors.primary,
214
- fontWeight: '500',
215
- },
216
- eventBadge: {
217
- backgroundColor: Colors.purple,
218
- paddingHorizontal: 12,
219
- paddingVertical: 5,
220
- borderRadius: 8,
221
- },
95
+ eventBadge: { backgroundColor: Colors.purple, paddingHorizontal: 12, paddingVertical: 5, borderRadius: 8 },
222
96
  eventBadgeText: { color: '#FFF', fontSize: 14, fontWeight: '700' },
223
97
  detailBody: { flex: 1 },
224
98
  detailBodyContent: { padding: 12, paddingBottom: 40 },
225
99
  sectionWithCopy: { gap: 8 },
226
-
227
- // Properties
228
100
  propsGrid: { gap: 12 },
229
101
  propRow: {},
230
102
  propKey: { fontSize: 13, fontWeight: '600', color: Colors.textSecondary, marginBottom: 3 },
231
103
  propValue: { fontSize: 14, color: Colors.text, lineHeight: 20 },
232
-
233
- // Timing
234
104
  timingCard: {
235
- backgroundColor: Colors.surface,
236
- borderRadius: 12,
237
- padding: 14,
238
- flexDirection: 'row',
239
- justifyContent: 'space-between',
240
- alignItems: 'center',
241
- marginTop: 4,
105
+ backgroundColor: Colors.surface, borderRadius: 12, padding: 14,
106
+ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: 4,
242
107
  },
243
108
  timingLabel: { fontSize: 13, color: Colors.textSecondary, fontWeight: '500' },
244
109
  timingValue: { fontSize: 13, color: Colors.text },
@@ -1,11 +1,11 @@
1
- import React, { useState } from 'react';
2
- import { View, Text, FlatList, TouchableOpacity, StyleSheet, Animated, ScrollView } from 'react-native';
3
- import { Colors } from '../utils/constants';
1
+ import React from 'react';
2
+ import { View, Text, StyleSheet, ScrollView } from 'react-native';
3
+ import { Colors } from '../utils/colors';
4
4
  import { safeStringify } from '../utils/safeStringify';
5
5
  import { CollapsibleSection } from './shared/CollapsibleSection';
6
6
  import { JsonView } from './shared/JsonView';
7
7
  import { CopyButton } from './shared/CopyButton';
8
- import { useSlideDetailAnimation } from '../hooks/useSlideDetailAnimation';
8
+ import { LogListScreen } from './shared/LogListScreen';
9
9
  import type { DebugFeatureRenderProps, ZustandLogEntry } from '../types';
10
10
 
11
11
  const getActionColor = (action: string): string => {
@@ -22,14 +22,25 @@ const getActionBgColor = (action: string): string => {
22
22
  return 'rgba(175,82,222,0.1)';
23
23
  };
24
24
 
25
+ function findChanges(prev: unknown, next: unknown): string[] {
26
+ if (typeof prev !== 'object' || typeof next !== 'object' || !prev || !next) return [];
27
+ const allKeys = new Set([...Object.keys(prev as object), ...Object.keys(next as object)]);
28
+ const changed: string[] = [];
29
+ allKeys.forEach((key) => {
30
+ const pv = (prev as Record<string, unknown>)[key];
31
+ const nv = (next as Record<string, unknown>)[key];
32
+ if (safeStringify(pv) !== safeStringify(nv)) changed.push(key);
33
+ });
34
+ return changed;
35
+ }
36
+
25
37
  export const ZustandLogTab: React.FC<DebugFeatureRenderProps<ZustandLogEntry>> = React.memo(({
26
38
  data,
27
- }) => {
28
- const [selected, setSelected] = useState<ZustandLogEntry | null>(null);
29
- const { detailTranslateX, listTranslateX, listOpacity } = useSlideDetailAnimation(selected);
30
-
31
- const renderItem = ({ item }: { item: ZustandLogEntry }) => (
32
- <TouchableOpacity style={s.card} onPress={() => setSelected(item)} activeOpacity={0.6}>
39
+ }) => (
40
+ <LogListScreen
41
+ data={data}
42
+ emptyText="No Zustand state changes"
43
+ renderRow={(item) => (
33
44
  <View style={s.cardRow}>
34
45
  <View style={[s.actionIcon, { backgroundColor: getActionBgColor(item.action) }]}>
35
46
  <View style={[s.actionDot, { backgroundColor: getActionColor(item.action) }]} />
@@ -51,148 +62,71 @@ export const ZustandLogTab: React.FC<DebugFeatureRenderProps<ZustandLogEntry>> =
51
62
  </View>
52
63
  )}
53
64
  </View>
54
- </TouchableOpacity>
55
- );
56
-
57
- const findChanges = (prev: unknown, next: unknown): string[] => {
58
- if (typeof prev !== 'object' || typeof next !== 'object' || !prev || !next) return [];
59
- const allKeys = new Set([...Object.keys(prev as object), ...Object.keys(next as object)]);
60
- const changed: string[] = [];
61
- allKeys.forEach((key) => {
62
- const pv = (prev as Record<string, unknown>)[key];
63
- const nv = (next as Record<string, unknown>)[key];
64
- if (safeStringify(pv) !== safeStringify(nv)) changed.push(key);
65
- });
66
- return changed;
67
- };
68
-
69
- return (
70
- <View style={s.container}>
71
- {/* List */}
72
- <Animated.View style={[s.listWrap, selected ? { opacity: listOpacity, transform: [{ translateX: listTranslateX }] } : null]}>
73
- {data.length === 0 ? (
74
- <View style={s.emptyContainer}>
75
- <Text style={s.emptyIcon}>~</Text>
76
- <Text style={s.empty}>No Zustand state changes</Text>
65
+ )}
66
+ renderDetailHeader={(item) => (
67
+ <View style={s.detailHeaderCenter}>
68
+ <Text style={[s.detailAction, { color: getActionColor(item.action) }]}>
69
+ {item.action}
70
+ </Text>
71
+ {item.storeName && (
72
+ <View style={s.storeBadge}>
73
+ <Text style={s.storeBadgeText}>{item.storeName}</Text>
77
74
  </View>
78
- ) : (
79
- <FlatList
80
- data={[...data].reverse()}
81
- renderItem={renderItem}
82
- keyExtractor={(item) => item.id}
83
- contentContainerStyle={s.listContent}
84
- initialNumToRender={20}
85
- maxToRenderPerBatch={10}
86
- windowSize={5}
87
- removeClippedSubviews={true}
88
- />
89
75
  )}
90
- </Animated.View>
91
-
92
- {/* Detail (push navigation) */}
93
- {selected && (
94
- <Animated.View style={[s.detailOverlay, { transform: [{ translateX: detailTranslateX }] }]}>
95
- <View style={s.detailWrap}>
96
- <View style={s.detailHeader}>
97
- <TouchableOpacity onPress={() => setSelected(null)} style={s.backBtn} activeOpacity={0.6}>
98
- <Text style={s.backIcon}>‹</Text>
99
- <Text style={s.backText}>Back</Text>
100
- </TouchableOpacity>
101
- <View style={s.detailHeaderCenter}>
102
- <Text style={[s.detailAction, { color: getActionColor(selected.action) }]}>
103
- {selected.action}
104
- </Text>
105
- {selected.storeName && (
106
- <View style={s.storeBadge}>
107
- <Text style={s.storeBadgeText}>{selected.storeName}</Text>
108
- </View>
109
- )}
110
- </View>
76
+ </View>
77
+ )}
78
+ renderDetailBody={(item) => {
79
+ const changes = findChanges(item.prevState, item.nextState);
80
+ return (
81
+ <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
82
+ <View style={s.metaCard}>
83
+ <View style={s.metaItem}>
84
+ <Text style={s.metaLabel}>Time</Text>
85
+ <Text style={s.metaValue}>{new Date(item.timestamp).toLocaleString()}</Text>
111
86
  </View>
112
- <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
113
- {/* Meta */}
114
- <View style={s.metaCard}>
115
- <View style={s.metaItem}>
116
- <Text style={s.metaLabel}>Time</Text>
117
- <Text style={s.metaValue}>
118
- {new Date(selected.timestamp).toLocaleString()}
119
- </Text>
120
- </View>
121
- {selected.actionCompleteTime != null && (
122
- <View style={s.metaDivider} />
123
- )}
124
- {selected.actionCompleteTime != null && (
125
- <View style={s.metaItem}>
126
- <Text style={s.metaLabel}>Duration</Text>
127
- <Text style={s.metaValue}>{selected.actionCompleteTime}ms</Text>
128
- </View>
129
- )}
87
+ {item.actionCompleteTime != null && <View style={s.metaDivider} />}
88
+ {item.actionCompleteTime != null && (
89
+ <View style={s.metaItem}>
90
+ <Text style={s.metaLabel}>Duration</Text>
91
+ <Text style={s.metaValue}>{item.actionCompleteTime}ms</Text>
130
92
  </View>
93
+ )}
94
+ </View>
131
95
 
132
- {/* Changed keys */}
133
- {(() => {
134
- const changes = findChanges(selected.prevState, selected.nextState);
135
- if (changes.length === 0) return null;
136
- return (
137
- <View style={s.changesCard}>
138
- <Text style={s.changesTitle}>Changed Keys</Text>
139
- <View style={s.changesTags}>
140
- {changes.map((key) => (
141
- <View key={key} style={s.changeTag}>
142
- <Text style={s.changeTagText}>{key}</Text>
143
- </View>
144
- ))}
145
- </View>
96
+ {changes.length > 0 && (
97
+ <View style={s.changesCard}>
98
+ <Text style={s.changesTitle}>Changed Keys</Text>
99
+ <View style={s.changesTags}>
100
+ {changes.map((key) => (
101
+ <View key={key} style={s.changeTag}>
102
+ <Text style={s.changeTagText}>{key}</Text>
146
103
  </View>
147
- );
148
- })()}
104
+ ))}
105
+ </View>
106
+ </View>
107
+ )}
149
108
 
150
- {/* Previous State */}
151
- <CollapsibleSection title="Previous State">
152
- <View style={s.sectionWithCopy}>
153
- <CopyButton text={safeStringify(selected.prevState, 2)} label="Previous State" />
154
- <JsonView data={selected.prevState} maxHeight={250} />
155
- </View>
156
- </CollapsibleSection>
109
+ <CollapsibleSection title="Previous State">
110
+ <View style={s.sectionWithCopy}>
111
+ <CopyButton text={safeStringify(item.prevState, 2)} label="Previous State" />
112
+ <JsonView data={item.prevState} maxHeight={250} />
113
+ </View>
114
+ </CollapsibleSection>
157
115
 
158
- {/* Next State */}
159
- <CollapsibleSection title="Next State" initiallyExpanded>
160
- <View style={s.sectionWithCopy}>
161
- <CopyButton text={safeStringify(selected.nextState, 2)} label="Next State" />
162
- <JsonView data={selected.nextState} maxHeight={250} />
163
- </View>
164
- </CollapsibleSection>
165
- </ScrollView>
166
- </View>
167
- </Animated.View>
168
- )}
169
- </View>
170
- );
171
- });
116
+ <CollapsibleSection title="Next State" initiallyExpanded>
117
+ <View style={s.sectionWithCopy}>
118
+ <CopyButton text={safeStringify(item.nextState, 2)} label="Next State" />
119
+ <JsonView data={item.nextState} maxHeight={250} />
120
+ </View>
121
+ </CollapsibleSection>
122
+ </ScrollView>
123
+ );
124
+ }}
125
+ />
126
+ ));
172
127
 
173
128
  const s = StyleSheet.create({
174
- container: { flex: 1, backgroundColor: Colors.background },
175
- listWrap: {
176
- position: 'absolute',
177
- top: 0,
178
- left: 0,
179
- right: 0,
180
- bottom: 0,
181
- },
182
- listContent: { padding: 12 },
183
-
184
- // Empty
185
- emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' },
186
- emptyIcon: { fontSize: 40, color: Colors.textLight, marginBottom: 4 },
187
- empty: { textAlign: 'center', color: Colors.textLight, fontSize: 14 },
188
-
189
- // Card
190
- card: {
191
- backgroundColor: Colors.surface,
192
- borderRadius: 12,
193
- marginBottom: 8,
194
- overflow: 'hidden',
195
- },
129
+ // Row
196
130
  cardRow: { flexDirection: 'row', padding: 14, alignItems: 'center' },
197
131
  actionIcon: {
198
132
  width: 28,
@@ -222,45 +156,7 @@ const s = StyleSheet.create({
222
156
  },
223
157
  durationText: { fontSize: 12, color: Colors.textSecondary, fontWeight: '500' },
224
158
 
225
- // Detail (push navigation)
226
- detailOverlay: {
227
- position: 'absolute',
228
- top: 0,
229
- left: 0,
230
- right: 0,
231
- bottom: 0,
232
- backgroundColor: Colors.background,
233
- },
234
- detailWrap: { flex: 1, backgroundColor: Colors.background },
235
- detailHeader: {
236
- flexDirection: 'row',
237
- alignItems: 'center',
238
- paddingHorizontal: 8,
239
- paddingVertical: 10,
240
- backgroundColor: Colors.surface,
241
- borderBottomWidth: StyleSheet.hairlineWidth,
242
- borderBottomColor: Colors.border,
243
- },
244
- backBtn: {
245
- flexDirection: 'row',
246
- alignItems: 'center',
247
- paddingHorizontal: 6,
248
- paddingVertical: 4,
249
- borderRadius: 8,
250
- marginRight: 8,
251
- },
252
- backIcon: {
253
- fontSize: 24,
254
- fontWeight: '300',
255
- color: Colors.primary,
256
- marginTop: -2,
257
- marginRight: 2,
258
- },
259
- backText: {
260
- fontSize: 16,
261
- color: Colors.primary,
262
- fontWeight: '500',
263
- },
159
+ // Detail header
264
160
  detailHeaderCenter: {
265
161
  flexDirection: 'row',
266
162
  alignItems: 'center',
@@ -268,6 +164,8 @@ const s = StyleSheet.create({
268
164
  flex: 1,
269
165
  },
270
166
  detailAction: { fontSize: 17, fontWeight: '700' },
167
+
168
+ // Detail body
271
169
  detailBody: { flex: 1 },
272
170
  detailBodyContent: { padding: 12, paddingBottom: 40 },
273
171
  sectionWithCopy: { gap: 8 },
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { View, Text, Pressable, StyleSheet, Animated } from 'react-native';
3
- import { Colors } from '../../utils/constants';
3
+ import { Colors } from '../../utils/colors';
4
4
 
5
5
  interface Props {
6
6
  title: string;
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useState } from 'react';
2
2
  import { TouchableOpacity, Text, StyleSheet } from 'react-native';
3
- import { Colors } from '../../utils/constants';
3
+ import { Colors } from '../../utils/colors';
4
4
  import { copyToComputer } from '../../utils/copyToComputer';
5
5
 
6
6
  interface CopyButtonProps {