react-native-debug-toolkit 3.3.4 → 3.5.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 (258) hide show
  1. package/README.md +48 -46
  2. package/README.zh-CN.md +48 -46
  3. package/android/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +0 -187
  4. package/bin/debug-toolkit.js +0 -16
  5. package/ios/DebugToolkitDevConnect.h +0 -12
  6. package/ios/DebugToolkitDevConnect.mm +0 -321
  7. package/lib/commonjs/constants/logLevels.js +19 -0
  8. package/lib/commonjs/constants/logLevels.js.map +1 -0
  9. package/lib/commonjs/core/initialize.js +36 -18
  10. package/lib/commonjs/core/initialize.js.map +1 -1
  11. package/lib/commonjs/features/console/ConsoleLogTab.js +4 -15
  12. package/lib/commonjs/features/console/ConsoleLogTab.js.map +1 -1
  13. package/lib/commonjs/features/console/index.js +15 -8
  14. package/lib/commonjs/features/console/index.js.map +1 -1
  15. package/lib/commonjs/features/devConnect/DevConnectTab.js +18 -470
  16. package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
  17. package/lib/commonjs/features/devConnect/devConnectPreferences.js +0 -12
  18. package/lib/commonjs/features/devConnect/devConnectPreferences.js.map +1 -1
  19. package/lib/commonjs/features/devConnect/devConnectUtils.js +2 -57
  20. package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
  21. package/lib/commonjs/features/devConnect/index.js +1 -23
  22. package/lib/commonjs/features/devConnect/index.js.map +1 -1
  23. package/lib/commonjs/features/devConnect/nativeDevConnect.js +1 -103
  24. package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
  25. package/lib/commonjs/features/network/NetworkLogTab.js +91 -93
  26. package/lib/commonjs/features/network/NetworkLogTab.js.map +1 -1
  27. package/lib/commonjs/features/network/index.js +7 -4
  28. package/lib/commonjs/features/network/index.js.map +1 -1
  29. package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js +1044 -0
  30. package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js.map +1 -0
  31. package/lib/commonjs/features/sessionHistory/index.js +103 -0
  32. package/lib/commonjs/features/sessionHistory/index.js.map +1 -0
  33. package/lib/commonjs/features/track/index.js +4 -3
  34. package/lib/commonjs/features/track/index.js.map +1 -1
  35. package/lib/commonjs/index.js +27 -0
  36. package/lib/commonjs/index.js.map +1 -1
  37. package/lib/commonjs/ui/DebugView.js +3 -0
  38. package/lib/commonjs/ui/DebugView.js.map +1 -1
  39. package/lib/commonjs/ui/panel/DebugPanel.js +67 -34
  40. package/lib/commonjs/ui/panel/DebugPanel.js.map +1 -1
  41. package/lib/commonjs/ui/panel/FeatureIntroCard.js +131 -0
  42. package/lib/commonjs/ui/panel/FeatureIntroCard.js.map +1 -0
  43. package/lib/commonjs/ui/panel/FeatureRail.js +163 -0
  44. package/lib/commonjs/ui/panel/FeatureRail.js.map +1 -0
  45. package/lib/commonjs/ui/panel/FloatPanelView.js +169 -32
  46. package/lib/commonjs/ui/panel/FloatPanelView.js.map +1 -1
  47. package/lib/commonjs/ui/panel/buildFeatureSummary.js +207 -0
  48. package/lib/commonjs/ui/panel/buildFeatureSummary.js.map +1 -0
  49. package/lib/commonjs/ui/panel/filterFeatureSnapshot.js +43 -0
  50. package/lib/commonjs/ui/panel/filterFeatureSnapshot.js.map +1 -0
  51. package/lib/commonjs/ui/panel/tabPersistence.js +17 -0
  52. package/lib/commonjs/ui/panel/tabPersistence.js.map +1 -0
  53. package/lib/commonjs/ui/theme/colors.js +6 -0
  54. package/lib/commonjs/ui/theme/colors.js.map +1 -1
  55. package/lib/commonjs/utils/DaemonClient.js +30 -8
  56. package/lib/commonjs/utils/DaemonClient.js.map +1 -1
  57. package/lib/commonjs/utils/SessionManager.js +132 -0
  58. package/lib/commonjs/utils/SessionManager.js.map +1 -0
  59. package/lib/commonjs/utils/StorageAdapter.js +104 -0
  60. package/lib/commonjs/utils/StorageAdapter.js.map +1 -0
  61. package/lib/commonjs/utils/createChannelFeature.js +22 -5
  62. package/lib/commonjs/utils/createChannelFeature.js.map +1 -1
  63. package/lib/commonjs/utils/createDebugTab.js +21 -0
  64. package/lib/commonjs/utils/createDebugTab.js.map +1 -0
  65. package/lib/commonjs/utils/createPersistedObservableStore.js +14 -8
  66. package/lib/commonjs/utils/createPersistedObservableStore.js.map +1 -1
  67. package/lib/commonjs/utils/debugPreferences.js +28 -6
  68. package/lib/commonjs/utils/debugPreferences.js.map +1 -1
  69. package/lib/commonjs/utils/deviceReport.js +5 -1
  70. package/lib/commonjs/utils/deviceReport.js.map +1 -1
  71. package/lib/commonjs/utils/logRuntime.js +32 -0
  72. package/lib/commonjs/utils/logRuntime.js.map +1 -0
  73. package/lib/module/constants/logLevels.js +15 -0
  74. package/lib/module/constants/logLevels.js.map +1 -0
  75. package/lib/module/core/initialize.js +36 -18
  76. package/lib/module/core/initialize.js.map +1 -1
  77. package/lib/module/features/console/ConsoleLogTab.js +1 -12
  78. package/lib/module/features/console/ConsoleLogTab.js.map +1 -1
  79. package/lib/module/features/console/index.js +15 -8
  80. package/lib/module/features/console/index.js.map +1 -1
  81. package/lib/module/features/devConnect/DevConnectTab.js +21 -473
  82. package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
  83. package/lib/module/features/devConnect/devConnectPreferences.js +1 -12
  84. package/lib/module/features/devConnect/devConnectPreferences.js.map +1 -1
  85. package/lib/module/features/devConnect/devConnectUtils.js +1 -53
  86. package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
  87. package/lib/module/features/devConnect/index.js +5 -9
  88. package/lib/module/features/devConnect/index.js.map +1 -1
  89. package/lib/module/features/devConnect/nativeDevConnect.js +1 -100
  90. package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
  91. package/lib/module/features/network/NetworkLogTab.js +91 -93
  92. package/lib/module/features/network/NetworkLogTab.js.map +1 -1
  93. package/lib/module/features/network/index.js +7 -4
  94. package/lib/module/features/network/index.js.map +1 -1
  95. package/lib/module/features/sessionHistory/SessionHistoryTab.js +1039 -0
  96. package/lib/module/features/sessionHistory/SessionHistoryTab.js.map +1 -0
  97. package/lib/module/features/sessionHistory/index.js +99 -0
  98. package/lib/module/features/sessionHistory/index.js.map +1 -0
  99. package/lib/module/features/track/index.js +4 -3
  100. package/lib/module/features/track/index.js.map +1 -1
  101. package/lib/module/index.js +4 -0
  102. package/lib/module/index.js.map +1 -1
  103. package/lib/module/ui/DebugView.js +3 -0
  104. package/lib/module/ui/DebugView.js.map +1 -1
  105. package/lib/module/ui/panel/DebugPanel.js +67 -34
  106. package/lib/module/ui/panel/DebugPanel.js.map +1 -1
  107. package/lib/module/ui/panel/FeatureIntroCard.js +126 -0
  108. package/lib/module/ui/panel/FeatureIntroCard.js.map +1 -0
  109. package/lib/module/ui/panel/FeatureRail.js +158 -0
  110. package/lib/module/ui/panel/FeatureRail.js.map +1 -0
  111. package/lib/module/ui/panel/FloatPanelView.js +170 -33
  112. package/lib/module/ui/panel/FloatPanelView.js.map +1 -1
  113. package/lib/module/ui/panel/buildFeatureSummary.js +203 -0
  114. package/lib/module/ui/panel/buildFeatureSummary.js.map +1 -0
  115. package/lib/module/ui/panel/filterFeatureSnapshot.js +39 -0
  116. package/lib/module/ui/panel/filterFeatureSnapshot.js.map +1 -0
  117. package/lib/module/ui/panel/tabPersistence.js +13 -0
  118. package/lib/module/ui/panel/tabPersistence.js.map +1 -0
  119. package/lib/module/ui/theme/colors.js +6 -0
  120. package/lib/module/ui/theme/colors.js.map +1 -1
  121. package/lib/module/utils/DaemonClient.js +30 -8
  122. package/lib/module/utils/DaemonClient.js.map +1 -1
  123. package/lib/module/utils/SessionManager.js +127 -0
  124. package/lib/module/utils/SessionManager.js.map +1 -0
  125. package/lib/module/utils/StorageAdapter.js +96 -0
  126. package/lib/module/utils/StorageAdapter.js.map +1 -0
  127. package/lib/module/utils/createChannelFeature.js +22 -5
  128. package/lib/module/utils/createChannelFeature.js.map +1 -1
  129. package/lib/module/utils/createDebugTab.js +17 -0
  130. package/lib/module/utils/createDebugTab.js.map +1 -0
  131. package/lib/module/utils/createPersistedObservableStore.js +14 -8
  132. package/lib/module/utils/createPersistedObservableStore.js.map +1 -1
  133. package/lib/module/utils/debugPreferences.js +27 -6
  134. package/lib/module/utils/debugPreferences.js.map +1 -1
  135. package/lib/module/utils/deviceReport.js +4 -1
  136. package/lib/module/utils/deviceReport.js.map +1 -1
  137. package/lib/module/utils/logRuntime.js +26 -0
  138. package/lib/module/utils/logRuntime.js.map +1 -0
  139. package/lib/typescript/src/constants/logLevels.d.ts +3 -0
  140. package/lib/typescript/src/constants/logLevels.d.ts.map +1 -0
  141. package/lib/typescript/src/core/initialize.d.ts +6 -0
  142. package/lib/typescript/src/core/initialize.d.ts.map +1 -1
  143. package/lib/typescript/src/features/console/ConsoleLogTab.d.ts.map +1 -1
  144. package/lib/typescript/src/features/console/index.d.ts +2 -1
  145. package/lib/typescript/src/features/console/index.d.ts.map +1 -1
  146. package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
  147. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts +0 -2
  148. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts.map +1 -1
  149. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +0 -20
  150. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
  151. package/lib/typescript/src/features/devConnect/index.d.ts +2 -2
  152. package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
  153. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +0 -25
  154. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
  155. package/lib/typescript/src/features/devConnect/types.d.ts +1 -3
  156. package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
  157. package/lib/typescript/src/features/network/NetworkLogTab.d.ts.map +1 -1
  158. package/lib/typescript/src/features/network/index.d.ts +2 -1
  159. package/lib/typescript/src/features/network/index.d.ts.map +1 -1
  160. package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts +20 -0
  161. package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts.map +1 -0
  162. package/lib/typescript/src/features/sessionHistory/index.d.ts +4 -0
  163. package/lib/typescript/src/features/sessionHistory/index.d.ts.map +1 -0
  164. package/lib/typescript/src/features/track/index.d.ts +2 -1
  165. package/lib/typescript/src/features/track/index.d.ts.map +1 -1
  166. package/lib/typescript/src/index.d.ts +6 -0
  167. package/lib/typescript/src/index.d.ts.map +1 -1
  168. package/lib/typescript/src/types/feature.d.ts +1 -1
  169. package/lib/typescript/src/types/feature.d.ts.map +1 -1
  170. package/lib/typescript/src/types/index.d.ts +2 -0
  171. package/lib/typescript/src/types/index.d.ts.map +1 -1
  172. package/lib/typescript/src/ui/DebugView.d.ts +4 -2
  173. package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
  174. package/lib/typescript/src/ui/panel/DebugPanel.d.ts +3 -1
  175. package/lib/typescript/src/ui/panel/DebugPanel.d.ts.map +1 -1
  176. package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts +11 -0
  177. package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts.map +1 -0
  178. package/lib/typescript/src/ui/panel/FeatureRail.d.ts +16 -0
  179. package/lib/typescript/src/ui/panel/FeatureRail.d.ts.map +1 -0
  180. package/lib/typescript/src/ui/panel/FloatPanelView.d.ts.map +1 -1
  181. package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts +13 -0
  182. package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts.map +1 -0
  183. package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts +3 -0
  184. package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts.map +1 -0
  185. package/lib/typescript/src/ui/panel/tabPersistence.d.ts +3 -0
  186. package/lib/typescript/src/ui/panel/tabPersistence.d.ts.map +1 -0
  187. package/lib/typescript/src/ui/theme/colors.d.ts +5 -0
  188. package/lib/typescript/src/ui/theme/colors.d.ts.map +1 -1
  189. package/lib/typescript/src/utils/DaemonClient.d.ts +7 -1
  190. package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
  191. package/lib/typescript/src/utils/SessionManager.d.ts +30 -0
  192. package/lib/typescript/src/utils/SessionManager.d.ts.map +1 -0
  193. package/lib/typescript/src/utils/StorageAdapter.d.ts +38 -0
  194. package/lib/typescript/src/utils/StorageAdapter.d.ts.map +1 -0
  195. package/lib/typescript/src/utils/createChannelFeature.d.ts +2 -0
  196. package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -1
  197. package/lib/typescript/src/utils/createDebugTab.d.ts +18 -0
  198. package/lib/typescript/src/utils/createDebugTab.d.ts.map +1 -0
  199. package/lib/typescript/src/utils/createPersistedObservableStore.d.ts +4 -1
  200. package/lib/typescript/src/utils/createPersistedObservableStore.d.ts.map +1 -1
  201. package/lib/typescript/src/utils/debugPreferences.d.ts +1 -4
  202. package/lib/typescript/src/utils/debugPreferences.d.ts.map +1 -1
  203. package/lib/typescript/src/utils/deviceReport.d.ts +1 -0
  204. package/lib/typescript/src/utils/deviceReport.d.ts.map +1 -1
  205. package/lib/typescript/src/utils/logRuntime.d.ts +13 -0
  206. package/lib/typescript/src/utils/logRuntime.d.ts.map +1 -0
  207. package/package.json +10 -6
  208. package/src/constants/logLevels.ts +13 -0
  209. package/src/core/initialize.ts +61 -21
  210. package/src/features/console/ConsoleLogTab.tsx +1 -14
  211. package/src/features/console/index.ts +18 -8
  212. package/src/features/devConnect/DevConnectTab.tsx +17 -381
  213. package/src/features/devConnect/devConnectPreferences.ts +0 -15
  214. package/src/features/devConnect/devConnectUtils.ts +1 -81
  215. package/src/features/devConnect/index.ts +2 -9
  216. package/src/features/devConnect/nativeDevConnect.ts +1 -136
  217. package/src/features/devConnect/types.ts +1 -3
  218. package/src/features/network/NetworkLogTab.tsx +61 -71
  219. package/src/features/network/index.ts +12 -3
  220. package/src/features/sessionHistory/SessionHistoryTab.tsx +691 -0
  221. package/src/features/sessionHistory/index.ts +102 -0
  222. package/src/features/track/index.ts +10 -3
  223. package/src/index.ts +13 -0
  224. package/src/types/feature.ts +2 -1
  225. package/src/types/index.ts +10 -0
  226. package/src/ui/DebugView.tsx +6 -1
  227. package/src/ui/panel/DebugPanel.tsx +60 -30
  228. package/src/ui/panel/FeatureIntroCard.tsx +127 -0
  229. package/src/ui/panel/FeatureRail.tsx +165 -0
  230. package/src/ui/panel/FloatPanelView.tsx +176 -25
  231. package/src/ui/panel/buildFeatureSummary.ts +288 -0
  232. package/src/ui/panel/filterFeatureSnapshot.ts +51 -0
  233. package/src/ui/panel/tabPersistence.ts +22 -0
  234. package/src/ui/theme/colors.ts +7 -0
  235. package/src/utils/DaemonClient.ts +33 -5
  236. package/src/utils/SessionManager.ts +174 -0
  237. package/src/utils/StorageAdapter.ts +135 -0
  238. package/src/utils/createChannelFeature.ts +28 -6
  239. package/src/utils/createDebugTab.ts +32 -0
  240. package/src/utils/createPersistedObservableStore.ts +18 -10
  241. package/src/utils/debugPreferences.ts +38 -8
  242. package/src/utils/deviceReport.ts +5 -1
  243. package/src/utils/logRuntime.ts +39 -0
  244. package/app.plugin.js +0 -51
  245. package/dev-client.js +0 -3
  246. package/lib/commonjs/ui/panel/FeatureTabBar.js +0 -182
  247. package/lib/commonjs/ui/panel/FeatureTabBar.js.map +0 -1
  248. package/lib/module/ui/panel/FeatureTabBar.js +0 -177
  249. package/lib/module/ui/panel/FeatureTabBar.js.map +0 -1
  250. package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts +0 -13
  251. package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts.map +0 -1
  252. package/scripts/bundle/android.js +0 -101
  253. package/scripts/bundle/cli.js +0 -57
  254. package/scripts/bundle/doctor.js +0 -38
  255. package/scripts/bundle/ios.js +0 -179
  256. package/scripts/bundle/setup.js +0 -39
  257. package/scripts/debug-bundle.gradle +0 -147
  258. package/src/ui/panel/FeatureTabBar.tsx +0 -204
@@ -1,57 +0,0 @@
1
- 'use strict';
2
-
3
- function readOption(args, name) {
4
- const index = args.indexOf(name);
5
- return index >= 0 ? args[index + 1] : undefined;
6
- }
7
-
8
- function hasFlag(args, name) {
9
- return args.includes(name);
10
- }
11
-
12
- function parseCommon(args, cwd) {
13
- return {
14
- cwd,
15
- platform: readOption(args, '--platform') || 'all',
16
- undo: hasFlag(args, '--undo'),
17
- check: hasFlag(args, '--check'),
18
- iosTarget: readOption(args, '--ios-target'),
19
- yes: hasFlag(args, '--yes'),
20
- };
21
- }
22
-
23
- async function runBundleCli(args, deps = {}) {
24
- const cwd = deps.cwd || process.cwd();
25
- const io = deps.io || {
26
- writeOut: (value) => process.stdout.write(value),
27
- writeErr: (value) => process.stderr.write(value),
28
- };
29
- const command = args[0];
30
-
31
- if (command === 'setup-bundle') {
32
- const setupBundle = deps.setupBundle || require('./setup').setupBundle;
33
- await setupBundle(parseCommon(args.slice(1), cwd));
34
- return 0;
35
- }
36
-
37
- if (command === 'doctor-bundle') {
38
- const doctorBundle = deps.doctorBundle || require('./doctor').doctorBundle;
39
- await doctorBundle({
40
- cwd,
41
- platform: readOption(args.slice(1), '--platform') || 'all',
42
- app: readOption(args.slice(1), '--app'),
43
- apk: readOption(args.slice(1), '--apk'),
44
- });
45
- return 0;
46
- }
47
-
48
- if (command === 'embed') {
49
- io.writeErr('Unknown command: embed\nUse: debug-toolkit setup-bundle\n');
50
- return 1;
51
- }
52
-
53
- io.writeErr(`Unknown command: ${command || '(none)'}\n`);
54
- return 1;
55
- }
56
-
57
- module.exports = { runBundleCli };
@@ -1,38 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { execFileSync } = require('child_process');
6
-
7
- function readZipEntriesWithUnzip(file) {
8
- const output = execFileSync('unzip', ['-Z1', file], { encoding: 'utf8' });
9
- return output.split(/\r?\n/).filter(Boolean);
10
- }
11
-
12
- async function doctorIos(options) {
13
- if (!options.app) throw new Error('--app is required for iOS doctor.');
14
- const bundle = path.join(options.app, 'main.jsbundle');
15
- if (!fs.existsSync(bundle)) {
16
- throw new Error(`main.jsbundle not found in ${options.app}`);
17
- }
18
- return { ok: true, platform: 'ios', bundle };
19
- }
20
-
21
- async function doctorAndroid(options) {
22
- if (!options.apk) throw new Error('--apk is required for Android doctor.');
23
- const readZipEntries = options.readZipEntries || readZipEntriesWithUnzip;
24
- const entries = await readZipEntries(options.apk);
25
- const bundle = entries.find((entry) => /^assets\/.+\.bundle$/.test(entry));
26
- if (!bundle) {
27
- throw new Error(`Android JS bundle not found in ${options.apk}`);
28
- }
29
- return { ok: true, platform: 'android', bundle };
30
- }
31
-
32
- async function doctorBundle(options) {
33
- if (options.platform === 'ios') return doctorIos(options);
34
- if (options.platform === 'android') return doctorAndroid(options);
35
- throw new Error(`Unsupported platform for doctor-bundle: ${options.platform}`);
36
- }
37
-
38
- module.exports = { doctorBundle, readZipEntriesWithUnzip };
@@ -1,179 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const xcode = require('xcode');
6
-
7
- const PHASE_NAME = 'Bundle React Native code and images';
8
- const BEGIN = '# react-native-debug-toolkit: begin debug bundle';
9
- const END = '# react-native-debug-toolkit: end debug bundle';
10
- const BLOCK = `${BEGIN}\nexport FORCE_BUNDLING=1\n${END}`;
11
-
12
- function stripQuotes(value) {
13
- return String(value || '').replace(/^"|"$/g, '');
14
- }
15
-
16
- function findProjects(cwd) {
17
- const iosDir = path.join(cwd, 'ios');
18
- if (!fs.existsSync(iosDir)) {
19
- return [];
20
- }
21
-
22
- return fs.readdirSync(iosDir)
23
- .filter((entry) => entry.endsWith('.xcodeproj') && entry !== 'Pods.xcodeproj')
24
- .map((entry) => path.join(iosDir, entry, 'project.pbxproj'))
25
- .filter((file) => fs.existsSync(file));
26
- }
27
-
28
- function decodeScript(value) {
29
- if (!value) {
30
- return '';
31
- }
32
-
33
- try {
34
- return JSON.parse(value);
35
- } catch {
36
- return stripQuotes(value);
37
- }
38
- }
39
-
40
- function encodeScript(value) {
41
- return JSON.stringify(value);
42
- }
43
-
44
- function phaseName(phase) {
45
- return stripQuotes(phase.name || phase.comment);
46
- }
47
-
48
- function isAppTarget(target) {
49
- return stripQuotes(target.productType) === 'com.apple.product-type.application';
50
- }
51
-
52
- function targetName(target) {
53
- return stripQuotes(target.name || target.productName || target.comment);
54
- }
55
-
56
- function targetBuildPhaseIds(target) {
57
- return (target.buildPhases || []).map((phaseRef) => {
58
- if (typeof phaseRef === 'string') {
59
- return phaseRef;
60
- }
61
- return phaseRef.value;
62
- });
63
- }
64
-
65
- function sectionEntries(objects, sectionName, isaName) {
66
- const section = objects[sectionName];
67
- if (section) {
68
- return Object.entries(section)
69
- .filter(([key]) => !key.endsWith('_comment'));
70
- }
71
-
72
- return Object.entries(objects)
73
- .filter(([key, value]) => !key.endsWith('_comment') && value && value.isa === isaName)
74
- .map(([key, value]) => [key, { ...value, comment: objects[`${key}_comment`] }]);
75
- }
76
-
77
- function loadTarget(cwd, iosTarget) {
78
- const projects = findProjects(cwd);
79
- if (projects.length !== 1) {
80
- throw new Error(`Expected one Xcode project, found ${projects.length}. Pass --ios-target after selecting the app project.`);
81
- }
82
-
83
- const pbxFile = projects[0];
84
- const proj = xcode.project(pbxFile).parseSync();
85
- const objects = proj.hash.project.objects;
86
- const nativeTargets = sectionEntries(objects, 'PBXNativeTarget', 'PBXNativeTarget');
87
- const shellPhases = new Map(sectionEntries(objects, 'PBXShellScriptBuildPhase', 'PBXShellScriptBuildPhase'));
88
-
89
- const appTargets = nativeTargets
90
- .filter(([, target]) => isAppTarget(target));
91
-
92
- const matches = iosTarget
93
- ? appTargets.filter(([, target]) => targetName(target) === iosTarget)
94
- : appTargets;
95
-
96
- if (matches.length !== 1) {
97
- throw new Error(`Expected one iOS app target, found ${matches.length}. Pass --ios-target <name>.`);
98
- }
99
-
100
- const [, target] = matches[0];
101
- for (const phaseId of targetBuildPhaseIds(target)) {
102
- const phase = shellPhases.get(phaseId);
103
- if (!phase || phaseName(phase) !== PHASE_NAME) {
104
- continue;
105
- }
106
-
107
- const script = decodeScript(phase.shellScript);
108
- if (!script.includes('react-native-xcode.sh') && !script.includes('with-environment.sh')) {
109
- throw new Error(`${PHASE_NAME} does not call React Native bundling script.`);
110
- }
111
-
112
- return { pbxFile, proj, phase };
113
- }
114
-
115
- throw new Error(`${PHASE_NAME} phase not found on iOS app target.`);
116
- }
117
-
118
- function insertBlock(script) {
119
- if (script.includes(BEGIN)) {
120
- return script;
121
- }
122
- return `${BLOCK}\n${script}`;
123
- }
124
-
125
- function removeBlock(script) {
126
- return script.replace(
127
- /# react-native-debug-toolkit: begin debug bundle\r?\nexport FORCE_BUNDLING=1\r?\n# react-native-debug-toolkit: end debug bundle\r?\n?/g,
128
- '',
129
- );
130
- }
131
-
132
- function writeProject(ctx, script) {
133
- ctx.phase.shellScript = encodeScript(script);
134
- fs.writeFileSync(ctx.pbxFile, ctx.proj.writeSync());
135
- }
136
-
137
- function setupIosBundle(options) {
138
- const ctx = loadTarget(options.cwd, options.iosTarget);
139
- const script = decodeScript(ctx.phase.shellScript);
140
- const next = insertBlock(script);
141
-
142
- if (next === script) {
143
- return { ok: true, changed: false };
144
- }
145
-
146
- writeProject(ctx, next);
147
- return { ok: true, changed: true };
148
- }
149
-
150
- function undoIosBundle(options) {
151
- const ctx = loadTarget(options.cwd, options.iosTarget);
152
- const script = decodeScript(ctx.phase.shellScript);
153
- const next = removeBlock(script);
154
-
155
- if (next === script) {
156
- return { ok: true, changed: false };
157
- }
158
-
159
- writeProject(ctx, next);
160
- return { ok: true, changed: true };
161
- }
162
-
163
- function checkIosBundle(options) {
164
- const ctx = loadTarget(options.cwd, options.iosTarget);
165
- const script = decodeScript(ctx.phase.shellScript);
166
-
167
- return {
168
- ok: script.includes(BLOCK),
169
- changed: false,
170
- };
171
- }
172
-
173
- module.exports = {
174
- setupIosBundle,
175
- undoIosBundle,
176
- checkIosBundle,
177
- BEGIN,
178
- END,
179
- };
@@ -1,39 +0,0 @@
1
- 'use strict';
2
-
3
- const { setupIosBundle, undoIosBundle, checkIosBundle } = require('./ios');
4
- const { setupAndroidBundle, undoAndroidBundle, checkAndroidBundle } = require('./android');
5
-
6
- async function setupBundle(options) {
7
- const platforms = options.platform === 'all' ? ['ios', 'android'] : [options.platform];
8
- const results = [];
9
-
10
- for (const platform of platforms) {
11
- if (platform === 'ios') {
12
- if (options.undo) {
13
- results.push(undoIosBundle(options));
14
- } else if (options.check) {
15
- results.push(checkIosBundle(options));
16
- } else {
17
- results.push(setupIosBundle(options));
18
- }
19
- continue;
20
- }
21
-
22
- if (platform === 'android') {
23
- if (options.undo) {
24
- results.push(undoAndroidBundle(options));
25
- } else if (options.check) {
26
- results.push(checkAndroidBundle(options));
27
- } else {
28
- results.push(setupAndroidBundle(options));
29
- }
30
- continue;
31
- }
32
-
33
- throw new Error(`Unsupported platform: ${platform}`);
34
- }
35
-
36
- return results;
37
- }
38
-
39
- module.exports = { setupBundle };
@@ -1,147 +0,0 @@
1
- // react-native-debug-toolkit: persistent debug/development bundle generation
2
-
3
- import java.util.Locale
4
- import javax.inject.Inject
5
- import org.gradle.api.DefaultTask
6
- import org.gradle.api.GradleException
7
- import org.gradle.api.file.DirectoryProperty
8
- import org.gradle.api.file.RegularFileProperty
9
- import org.gradle.api.provider.ListProperty
10
- import org.gradle.api.provider.Property
11
- import org.gradle.api.tasks.Input
12
- import org.gradle.api.tasks.InputDirectory
13
- import org.gradle.api.tasks.InputFile
14
- import org.gradle.api.tasks.Optional
15
- import org.gradle.api.tasks.OutputDirectory
16
- import org.gradle.api.tasks.TaskAction
17
- import org.gradle.process.ExecOperations
18
-
19
- abstract class DebugToolkitBundleTask extends DefaultTask {
20
- @Inject
21
- abstract ExecOperations getExecOperations()
22
-
23
- @InputDirectory
24
- abstract DirectoryProperty getRoot()
25
-
26
- @InputFile
27
- abstract RegularFileProperty getCliFile()
28
-
29
- @InputFile
30
- @Optional
31
- abstract RegularFileProperty getEntryFile()
32
-
33
- @InputFile
34
- @Optional
35
- abstract RegularFileProperty getBundleConfig()
36
-
37
- @Input
38
- abstract ListProperty<String> getNodeExecutableAndArgs()
39
-
40
- @Input
41
- abstract Property<String> getBundleCommand()
42
-
43
- @Input
44
- abstract Property<String> getBundleAssetName()
45
-
46
- @Input
47
- abstract ListProperty<String> getExtraPackagerArgs()
48
-
49
- @OutputDirectory
50
- abstract DirectoryProperty getJsBundleDir()
51
-
52
- @OutputDirectory
53
- abstract DirectoryProperty getResourcesDir()
54
-
55
- @TaskAction
56
- void run() {
57
- def rootFile = root.get().asFile
58
- def bundleOutput = new File(jsBundleDir.get().asFile, bundleAssetName.get())
59
- def entry = resolveEntryFile(rootFile)
60
- jsBundleDir.get().asFile.mkdirs()
61
- resourcesDir.get().asFile.mkdirs()
62
-
63
- def command = []
64
- command.addAll(nodeExecutableAndArgs.get())
65
- command.add(cliFile.get().asFile.absolutePath)
66
- command.add(bundleCommand.get())
67
- command.addAll([
68
- "--platform", "android",
69
- "--dev", "true",
70
- "--entry-file", entry.absolutePath,
71
- "--bundle-output", bundleOutput.absolutePath,
72
- "--assets-dest", resourcesDir.get().asFile.absolutePath,
73
- ])
74
-
75
- if (bundleConfig.isPresent()) {
76
- command.add("--config")
77
- command.add(bundleConfig.get().asFile.absolutePath)
78
- }
79
-
80
- command.addAll(extraPackagerArgs.get())
81
-
82
- execOperations.exec {
83
- workingDir(rootFile)
84
- commandLine(command)
85
- }
86
- }
87
-
88
- private File resolveEntryFile(File rootFile) {
89
- if (entryFile.isPresent()) {
90
- return entryFile.get().asFile
91
- }
92
-
93
- def androidEntry = new File(rootFile, "index.android.js")
94
- return androidEntry.exists() ? androidEntry : new File(rootFile, "index.js")
95
- }
96
- }
97
-
98
- def toolkitCapitalize = { String value ->
99
- value.length() == 0 ? value : value.substring(0, 1).toUpperCase(Locale.ROOT) + value.substring(1)
100
- }
101
-
102
- def toolkitReactExt = project.extensions.findByName("react")
103
- def toolkitAndroidComponents = project.extensions.findByName("androidComponents")
104
-
105
- if (toolkitAndroidComponents == null) {
106
- throw new GradleException("react-native-debug-toolkit debug-bundle.gradle requires the Android Gradle Plugin.")
107
- }
108
-
109
- def toolkitDefaultRoot = project.rootProject.layout.projectDirectory.dir("../")
110
- def toolkitDebuggableVariants = toolkitReactExt?.debuggableVariants?.getOrElse(["debug"]) ?: ["debug"]
111
-
112
- toolkitAndroidComponents.onVariants(toolkitAndroidComponents.selector().all()) { variant ->
113
- def variantName = variant.name
114
- def isDebuggable = toolkitDebuggableVariants.any { it.equalsIgnoreCase(variantName) }
115
-
116
- if (!isDebuggable) {
117
- return
118
- }
119
-
120
- def capName = toolkitCapitalize(variantName)
121
- def bundleTask = tasks.register("createDebugToolkit${capName}JsAndAssets", DebugToolkitBundleTask) {
122
- group = "react"
123
- description = "Generate embedded React Native JS bundle for ${variantName} debug build."
124
-
125
- root.set(toolkitReactExt?.root ?: toolkitDefaultRoot)
126
- cliFile.set(toolkitReactExt?.cliFile ?: root.file("node_modules/react-native/cli.js"))
127
- if (toolkitReactExt?.entryFile?.isPresent()) {
128
- entryFile.set(toolkitReactExt.entryFile)
129
- }
130
- if (toolkitReactExt?.bundleConfig?.isPresent()) {
131
- bundleConfig.set(toolkitReactExt.bundleConfig)
132
- }
133
- nodeExecutableAndArgs.set(toolkitReactExt?.nodeExecutableAndArgs ?: ["node"])
134
- bundleCommand.set(toolkitReactExt?.bundleCommand ?: "bundle")
135
- bundleAssetName.set(toolkitReactExt?.bundleAssetName ?: "index.android.bundle")
136
- extraPackagerArgs.set(toolkitReactExt?.extraPackagerArgs ?: [])
137
- jsBundleDir.set(project.layout.buildDirectory.dir("generated/assets/react-native-debug-toolkit/${variantName}"))
138
- resourcesDir.set(project.layout.buildDirectory.dir("generated/res/react-native-debug-toolkit/${variantName}"))
139
- }
140
-
141
- variant.sources.assets?.addGeneratedSourceDirectory(bundleTask) { task ->
142
- task.jsBundleDir
143
- }
144
- variant.sources.res?.addGeneratedSourceDirectory(bundleTask) { task ->
145
- task.resourcesDir
146
- }
147
- }
@@ -1,204 +0,0 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import {
3
- View,
4
- Text,
5
- StyleSheet,
6
- Animated,
7
- ScrollView,
8
- TouchableOpacity,
9
- } from 'react-native';
10
- import { Colors } from '../theme/colors';
11
-
12
- export interface TabItem {
13
- id: string;
14
- label: string;
15
- }
16
-
17
- interface FeatureTabBarProps {
18
- tabs: TabItem[];
19
- activeIndex: number;
20
- onSelectTab: (index: number) => void;
21
- }
22
-
23
- export function FeatureTabBar({ tabs, activeIndex, onSelectTab }: FeatureTabBarProps) {
24
- const [underlineWidth, setUnderlineWidth] = useState(0);
25
- const underlineTranslateX = useRef(new Animated.Value(0)).current;
26
- const tabScrollViewRef = useRef<ScrollView>(null);
27
- const tabLayouts = useRef<Array<{ x: number; width: number }>>([]);
28
- const tabScrollOffset = useRef(0);
29
- const tabViewportWidth = useRef(0);
30
- const tabContentWidth = useRef(0);
31
- const underlineInit = useRef(false);
32
- const isSwitching = useRef(false);
33
-
34
- const maxTabScroll = useCallback(
35
- () => Math.max(0, tabContentWidth.current - tabViewportWidth.current),
36
- [],
37
- );
38
- const clampScroll = useCallback(
39
- (offset: number) => Math.min(Math.max(0, offset), maxTabScroll()),
40
- [maxTabScroll],
41
- );
42
- const getTabScrollTarget = useCallback(
43
- (index: number) => {
44
- const layout = tabLayouts.current[index];
45
- return layout ? clampScroll(layout.x - 60) : clampScroll(tabScrollOffset.current);
46
- },
47
- [clampScroll],
48
- );
49
-
50
- const animateUnderline = useCallback(
51
- (index: number, scrollOffset?: number) => {
52
- const layout = tabLayouts.current[index];
53
- if (!layout) return;
54
- const offsetX = clampScroll(scrollOffset ?? tabScrollOffset.current);
55
- setUnderlineWidth(layout.width);
56
- Animated.spring(underlineTranslateX, {
57
- toValue: layout.x - offsetX,
58
- friction: 7,
59
- tension: 50,
60
- useNativeDriver: true,
61
- }).start();
62
- },
63
- [clampScroll, underlineTranslateX],
64
- );
65
-
66
- const syncUnderlineToActiveTab = useCallback(() => {
67
- const layout = tabLayouts.current[activeIndex];
68
- if (!layout) return;
69
- const clamped = clampScroll(tabScrollOffset.current);
70
- if (clamped !== tabScrollOffset.current) tabScrollOffset.current = clamped;
71
- underlineTranslateX.setValue(layout.x - clamped);
72
- setUnderlineWidth(layout.width);
73
- }, [activeIndex, clampScroll, underlineTranslateX]);
74
-
75
- const tryInit = useCallback(() => {
76
- if (underlineInit.current || tabViewportWidth.current <= 0 || tabContentWidth.current <= 0)
77
- return;
78
- const layout = tabLayouts.current[activeIndex];
79
- if (!layout) return;
80
- const target = getTabScrollTarget(activeIndex);
81
- tabScrollOffset.current = target;
82
- tabScrollViewRef.current?.scrollTo({ x: target, animated: false });
83
- underlineTranslateX.setValue(layout.x - target);
84
- setUnderlineWidth(layout.width);
85
- underlineInit.current = true;
86
- }, [activeIndex, getTabScrollTarget, underlineTranslateX]);
87
-
88
- const handleSelectTab = useCallback(
89
- (index: number) => {
90
- if (isSwitching.current || index === activeIndex) return;
91
- isSwitching.current = true;
92
-
93
- const layout = tabLayouts.current[index];
94
- if (layout) {
95
- const target = getTabScrollTarget(index);
96
- tabScrollOffset.current = target;
97
- tabScrollViewRef.current?.scrollTo({ x: target, animated: true });
98
- animateUnderline(index, target);
99
- }
100
-
101
- onSelectTab(index);
102
- setTimeout(() => {
103
- isSwitching.current = false;
104
- }, 350);
105
- },
106
- [activeIndex, animateUnderline, getTabScrollTarget, onSelectTab],
107
- );
108
-
109
- // React to external activeIndex changes (e.g. swipe-to-switch)
110
- useEffect(() => {
111
- if (!underlineInit.current) return;
112
- const layout = tabLayouts.current[activeIndex];
113
- if (!layout) return;
114
- const target = getTabScrollTarget(activeIndex);
115
- tabScrollOffset.current = target;
116
- tabScrollViewRef.current?.scrollTo({ x: target, animated: true });
117
- animateUnderline(activeIndex, target);
118
- }, [activeIndex, animateUnderline, getTabScrollTarget]);
119
-
120
- return (
121
- <View style={styles.container}>
122
- <ScrollView
123
- ref={tabScrollViewRef}
124
- horizontal
125
- showsHorizontalScrollIndicator={false}
126
- contentContainerStyle={styles.scrollContent}
127
- onLayout={(e) => {
128
- tabViewportWidth.current = e.nativeEvent.layout.width;
129
- tryInit();
130
- }}
131
- onContentSizeChange={(width) => {
132
- tabContentWidth.current = width;
133
- tryInit();
134
- }}
135
- onScroll={(e) => {
136
- tabScrollOffset.current = clampScroll(e.nativeEvent.contentOffset.x);
137
- if (!isSwitching.current) syncUnderlineToActiveTab();
138
- }}
139
- scrollEventThrottle={16}
140
- >
141
- {tabs.map((tab, index) => (
142
- <TouchableOpacity
143
- key={tab.id}
144
- style={styles.tab}
145
- onPress={() => handleSelectTab(index)}
146
- activeOpacity={0.7}
147
- onLayout={(e) => {
148
- const { x, width } = e.nativeEvent.layout;
149
- tabLayouts.current[index] = { x, width };
150
- if (index === activeIndex) tryInit();
151
- }}
152
- >
153
- <Text
154
- style={[styles.tabText, activeIndex === index && styles.activeTabText]}
155
- numberOfLines={1}
156
- >
157
- {tab.label}
158
- </Text>
159
- </TouchableOpacity>
160
- ))}
161
- </ScrollView>
162
- <Animated.View
163
- style={[
164
- styles.underline,
165
- { width: underlineWidth, transform: [{ translateX: underlineTranslateX }] },
166
- ]}
167
- />
168
- </View>
169
- );
170
- }
171
-
172
- const styles = StyleSheet.create({
173
- container: {
174
- backgroundColor: Colors.surface,
175
- borderBottomWidth: StyleSheet.hairlineWidth,
176
- borderBottomColor: Colors.border,
177
- },
178
- scrollContent: {
179
- paddingHorizontal: 20,
180
- flexDirection: 'row',
181
- },
182
- tab: {
183
- paddingVertical: 10,
184
- paddingHorizontal: 14,
185
- marginRight: 8,
186
- },
187
- tabText: {
188
- fontSize: 14,
189
- fontWeight: '500',
190
- color: Colors.textLight,
191
- },
192
- activeTabText: {
193
- color: Colors.primary,
194
- fontWeight: '600',
195
- },
196
- underline: {
197
- position: 'absolute',
198
- bottom: 0,
199
- left: 0,
200
- height: 2.5,
201
- borderRadius: 1.25,
202
- backgroundColor: Colors.primary,
203
- },
204
- });