react-native-debug-toolkit 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/android/build.gradle +30 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/java/com/debugtoolkit/BuildTypeModule.java +3 -27
- package/android/src/main/java/com/reactnative/debuglibs/RNDebugLibsModule.java +68 -0
- package/android/src/main/java/com/reactnative/debuglibs/RNDebugLibsPackage.java +28 -0
- package/ios/BuildTypeModule.h +5 -0
- package/ios/BuildTypeModule.m +6 -35
- package/ios/RNDebugLibs.h +10 -0
- package/ios/RNDebugLibs.m +79 -0
- package/lib/NativeDebugLibs.js +55 -0
- package/lib/features/ThirdPartyLibsFeature.js +65 -0
- package/lib/index.js +12 -2
- package/lib/views/FloatPanelView.js +5 -0
- package/lib/views/SubViewThirdPartyLibs.js +239 -0
- package/package.json +2 -1
- package/react-native-debug-toolkit.podspec +25 -0
- package/react-native.config.js +13 -0
package/README.md
CHANGED
|
@@ -10,6 +10,24 @@ npm install react-native-debug-toolkit
|
|
|
10
10
|
yarn add react-native-debug-toolkit
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
### iOS Additional Setup
|
|
14
|
+
|
|
15
|
+
This toolkit uses FLEX and DoraemonKit for iOS debugging features. To properly integrate:
|
|
16
|
+
|
|
17
|
+
1. Make sure CocoaPods is installed in your project
|
|
18
|
+
2. Add these dependencies to your Podfile:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
pod 'FLEX', :configurations => ['Debug']
|
|
22
|
+
pod 'DoraemonKit/Core', :configurations => ['Debug']
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
3. Run pod install in your iOS directory:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd ios && pod install
|
|
29
|
+
```
|
|
30
|
+
|
|
13
31
|
## Basic Usage
|
|
14
32
|
|
|
15
33
|
```javascript
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
2
|
+
|
|
3
|
+
android {
|
|
4
|
+
compileSdkVersion rootProject.ext.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 30
|
|
5
|
+
buildToolsVersion rootProject.ext.hasProperty('buildToolsVersion') ? rootProject.ext.buildToolsVersion : "30.0.3"
|
|
6
|
+
|
|
7
|
+
defaultConfig {
|
|
8
|
+
minSdkVersion rootProject.ext.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 21
|
|
9
|
+
targetSdkVersion rootProject.ext.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 30
|
|
10
|
+
versionCode 1
|
|
11
|
+
versionName "1.0"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
compileOptions {
|
|
15
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
16
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
repositories {
|
|
21
|
+
mavenCentral()
|
|
22
|
+
maven { url "https://jitpack.io" }
|
|
23
|
+
google()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
dependencies {
|
|
27
|
+
implementation "com.facebook.react:react-native:+"
|
|
28
|
+
implementation 'io.github.didi.dokit:dokitx:3.7.1'
|
|
29
|
+
implementation 'com.android.volley:volley:1.2.0'
|
|
30
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
package="com.reactnative.debuglibs">
|
|
4
|
+
|
|
5
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
6
|
+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
|
7
|
+
|
|
8
|
+
</manifest>
|
|
@@ -4,7 +4,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
|
|
4
4
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
5
5
|
import com.facebook.react.bridge.ReactMethod;
|
|
6
6
|
import com.facebook.react.bridge.Promise;
|
|
7
|
-
import com.facebook.react.bridge.Callback;
|
|
8
7
|
|
|
9
8
|
import java.util.HashMap;
|
|
10
9
|
import java.util.Map;
|
|
@@ -25,36 +24,13 @@ public class BuildTypeModule extends ReactContextBaseJavaModule {
|
|
|
25
24
|
@Override
|
|
26
25
|
public Map<String, Object> getConstants() {
|
|
27
26
|
final Map<String, Object> constants = new HashMap<>();
|
|
28
|
-
constants.put("
|
|
27
|
+
constants.put("buildType", BuildConfig.DEBUG ? "debug" : "release");
|
|
29
28
|
return constants;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
@ReactMethod
|
|
33
|
-
public void isDebugMode(Promise promise) {
|
|
34
|
-
try {
|
|
35
|
-
promise.resolve(BuildConfig.DEBUG);
|
|
36
|
-
} catch (Exception e) {
|
|
37
|
-
promise.reject("ERR_UNEXPECTED", e.getMessage(), e);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
@ReactMethod
|
|
42
|
-
public void isReleaseMode(Promise promise) {
|
|
43
|
-
try {
|
|
44
|
-
promise.resolve(!BuildConfig.DEBUG);
|
|
45
|
-
} catch (Exception e) {
|
|
46
|
-
promise.reject("ERR_UNEXPECTED", e.getMessage(), e);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
51
|
-
public Boolean isDebugModeSync() {
|
|
52
|
-
return BuildConfig.DEBUG;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
31
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
56
|
-
public
|
|
57
|
-
return
|
|
32
|
+
public String getBuildTypeSync() {
|
|
33
|
+
return BuildConfig.DEBUG ? "debug" : "release";
|
|
58
34
|
}
|
|
59
35
|
|
|
60
36
|
@ReactMethod
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package com.reactnative.debuglibs;
|
|
2
|
+
|
|
3
|
+
import android.app.Application;
|
|
4
|
+
import android.widget.Toast;
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
9
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
10
|
+
|
|
11
|
+
import io.github.didi.dokit.DoKit;
|
|
12
|
+
import io.github.didi.dokit.kit.AbstractKit;
|
|
13
|
+
|
|
14
|
+
import java.util.ArrayList;
|
|
15
|
+
import java.util.List;
|
|
16
|
+
|
|
17
|
+
public class RNDebugLibsModule extends ReactContextBaseJavaModule {
|
|
18
|
+
private final ReactApplicationContext reactContext;
|
|
19
|
+
|
|
20
|
+
public RNDebugLibsModule(ReactApplicationContext reactContext) {
|
|
21
|
+
super(reactContext);
|
|
22
|
+
this.reactContext = reactContext;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@NonNull
|
|
26
|
+
@Override
|
|
27
|
+
public String getName() {
|
|
28
|
+
return "RNDebugLibs";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@ReactMethod
|
|
32
|
+
public void showExplorer() {
|
|
33
|
+
// FLEX is iOS only
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@ReactMethod
|
|
37
|
+
public void hideExplorer() {
|
|
38
|
+
// FLEX is iOS only
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@ReactMethod
|
|
42
|
+
public void toggleExplorer() {
|
|
43
|
+
// FLEX is iOS only
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@ReactMethod
|
|
47
|
+
public void installDoraemonKit(String productId) {
|
|
48
|
+
Application app = (Application) reactContext.getApplicationContext();
|
|
49
|
+
List<AbstractKit> kits = new ArrayList<>();
|
|
50
|
+
// Initialize DoKit with custom kits if needed
|
|
51
|
+
DoKit.Builder(app)
|
|
52
|
+
.productId(productId)
|
|
53
|
+
.customKits(kits)
|
|
54
|
+
.build();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@ReactMethod
|
|
58
|
+
public void showDoraemonKit() {
|
|
59
|
+
Toast.makeText(reactContext, "showDoraemonKit被调用", Toast.LENGTH_SHORT).show();
|
|
60
|
+
DoKit.showToolPanel();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@ReactMethod
|
|
64
|
+
public void hideDoraemonKit() {
|
|
65
|
+
Toast.makeText(reactContext, "hideDoraemonKit被调用", Toast.LENGTH_SHORT).show();
|
|
66
|
+
DoKit.hideToolPanel();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.reactnative.debuglibs;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.ReactPackage;
|
|
6
|
+
import com.facebook.react.bridge.NativeModule;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
9
|
+
|
|
10
|
+
import java.util.ArrayList;
|
|
11
|
+
import java.util.Collections;
|
|
12
|
+
import java.util.List;
|
|
13
|
+
|
|
14
|
+
public class RNDebugLibsPackage implements ReactPackage {
|
|
15
|
+
@NonNull
|
|
16
|
+
@Override
|
|
17
|
+
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
|
|
18
|
+
List<NativeModule> modules = new ArrayList<>();
|
|
19
|
+
modules.add(new RNDebugLibsModule(reactContext));
|
|
20
|
+
return modules;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@NonNull
|
|
24
|
+
@Override
|
|
25
|
+
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
26
|
+
return Collections.emptyList();
|
|
27
|
+
}
|
|
28
|
+
}
|
package/ios/BuildTypeModule.h
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* BuildTypeModule
|
|
5
|
+
* Native module that provides information about the current build type (debug or release)
|
|
6
|
+
* Used to conditionally enable debugging tools only in debug builds
|
|
7
|
+
*/
|
|
3
8
|
@interface BuildTypeModule : NSObject <RCTBridgeModule>
|
|
4
9
|
@end
|
package/ios/BuildTypeModule.m
CHANGED
|
@@ -12,49 +12,20 @@ RCT_EXPORT_MODULE();
|
|
|
12
12
|
- (NSDictionary *)constantsToExport
|
|
13
13
|
{
|
|
14
14
|
#ifdef DEBUG
|
|
15
|
-
|
|
15
|
+
NSString *buildType = @"debug";
|
|
16
16
|
#else
|
|
17
|
-
|
|
17
|
+
NSString *buildType = @"release";
|
|
18
18
|
#endif
|
|
19
19
|
|
|
20
|
-
return @{ @"
|
|
20
|
+
return @{ @"buildType": buildType };
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(
|
|
23
|
+
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getBuildTypeSync)
|
|
24
24
|
{
|
|
25
25
|
#ifdef DEBUG
|
|
26
|
-
return @
|
|
26
|
+
return @"debug";
|
|
27
27
|
#else
|
|
28
|
-
return @
|
|
29
|
-
#endif
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isReleaseModeSync)
|
|
33
|
-
{
|
|
34
|
-
#ifdef DEBUG
|
|
35
|
-
return @(NO);
|
|
36
|
-
#else
|
|
37
|
-
return @(YES);
|
|
38
|
-
#endif
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
RCT_EXPORT_METHOD(isDebugMode:(RCTPromiseResolveBlock)resolve
|
|
42
|
-
rejecter:(RCTPromiseRejectBlock)reject)
|
|
43
|
-
{
|
|
44
|
-
#ifdef DEBUG
|
|
45
|
-
resolve(@(YES));
|
|
46
|
-
#else
|
|
47
|
-
resolve(@(NO));
|
|
48
|
-
#endif
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
RCT_EXPORT_METHOD(isReleaseMode:(RCTPromiseResolveBlock)resolve
|
|
52
|
-
rejecter:(RCTPromiseRejectBlock)reject)
|
|
53
|
-
{
|
|
54
|
-
#ifdef DEBUG
|
|
55
|
-
resolve(@(NO));
|
|
56
|
-
#else
|
|
57
|
-
resolve(@(YES));
|
|
28
|
+
return @"release";
|
|
58
29
|
#endif
|
|
59
30
|
}
|
|
60
31
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* RNDebugLibs
|
|
5
|
+
* Native module that provides access to FLEX and DoraemonKit debugging tools
|
|
6
|
+
* Note: These debugging tools are only available in DEBUG builds
|
|
7
|
+
*/
|
|
8
|
+
@interface RNDebugLibs : NSObject <RCTBridgeModule>
|
|
9
|
+
|
|
10
|
+
@end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#import "RNDebugLibs.h"
|
|
2
|
+
|
|
3
|
+
#ifdef DEBUG
|
|
4
|
+
#import "FLEXManager.h"
|
|
5
|
+
#import <DoraemonKit/DoraemonManager.h>
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
@implementation RNDebugLibs
|
|
9
|
+
|
|
10
|
+
// Export the module
|
|
11
|
+
RCT_EXPORT_MODULE();
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_METHOD(showExplorer)
|
|
14
|
+
{
|
|
15
|
+
#ifdef DEBUG
|
|
16
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
17
|
+
[[FLEXManager sharedManager] showExplorer];
|
|
18
|
+
});
|
|
19
|
+
#else
|
|
20
|
+
NSLog(@"[RNDebugLibs] showExplorer is only available in DEBUG builds");
|
|
21
|
+
#endif
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
RCT_EXPORT_METHOD(hideExplorer)
|
|
25
|
+
{
|
|
26
|
+
#ifdef DEBUG
|
|
27
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
28
|
+
[[FLEXManager sharedManager] hideExplorer];
|
|
29
|
+
});
|
|
30
|
+
#else
|
|
31
|
+
NSLog(@"[RNDebugLibs] hideExplorer is only available in DEBUG builds");
|
|
32
|
+
#endif
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
RCT_EXPORT_METHOD(toggleExplorer)
|
|
36
|
+
{
|
|
37
|
+
#ifdef DEBUG
|
|
38
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
39
|
+
[[FLEXManager sharedManager] toggleExplorer];
|
|
40
|
+
});
|
|
41
|
+
#else
|
|
42
|
+
NSLog(@"[RNDebugLibs] toggleExplorer is only available in DEBUG builds");
|
|
43
|
+
#endif
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
RCT_EXPORT_METHOD(installDoraemonKit:(NSString *)productId)
|
|
47
|
+
{
|
|
48
|
+
#ifdef DEBUG
|
|
49
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
50
|
+
[[DoraemonManager shareInstance] installWithPid:productId];
|
|
51
|
+
});
|
|
52
|
+
#else
|
|
53
|
+
NSLog(@"[RNDebugLibs] installDoraemonKit is only available in DEBUG builds");
|
|
54
|
+
#endif
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
RCT_EXPORT_METHOD(showDoraemonKit)
|
|
58
|
+
{
|
|
59
|
+
#ifdef DEBUG
|
|
60
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
61
|
+
[[DoraemonManager shareInstance] showDoraemon];
|
|
62
|
+
});
|
|
63
|
+
#else
|
|
64
|
+
NSLog(@"[RNDebugLibs] showDoraemonKit is only available in DEBUG builds");
|
|
65
|
+
#endif
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
RCT_EXPORT_METHOD(hideDoraemonKit)
|
|
69
|
+
{
|
|
70
|
+
#ifdef DEBUG
|
|
71
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
72
|
+
[[DoraemonManager shareInstance] hiddenDoraemon];
|
|
73
|
+
});
|
|
74
|
+
#else
|
|
75
|
+
NSLog(@"[RNDebugLibs] hideDoraemonKit is only available in DEBUG builds");
|
|
76
|
+
#endif
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native'
|
|
2
|
+
|
|
3
|
+
// 添加调试日志,查看是否正确获取了RNDebugLibs模块
|
|
4
|
+
const { RNDebugLibs } = NativeModules
|
|
5
|
+
console.log('Available Native Modules:', Object.keys(NativeModules))
|
|
6
|
+
console.log('RNDebugLibs module loaded:', !!RNDebugLibs)
|
|
7
|
+
|
|
8
|
+
export default class NativeDebugLibs {
|
|
9
|
+
// FLEX methods (iOS only)
|
|
10
|
+
static showExplorer() {
|
|
11
|
+
if (Platform.OS === 'ios' && RNDebugLibs) {
|
|
12
|
+
RNDebugLibs.showExplorer()
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static hideExplorer() {
|
|
17
|
+
if (Platform.OS === 'ios' && RNDebugLibs) {
|
|
18
|
+
RNDebugLibs.hideExplorer()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static toggleExplorer() {
|
|
23
|
+
if (Platform.OS === 'ios' && RNDebugLibs) {
|
|
24
|
+
RNDebugLibs.toggleExplorer()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// DoraemonKit/DoKit methods
|
|
29
|
+
static installDoraemonKit(productId) {
|
|
30
|
+
console.log('Calling installDoraemonKit with:', productId)
|
|
31
|
+
if (RNDebugLibs) {
|
|
32
|
+
RNDebugLibs.installDoraemonKit(productId)
|
|
33
|
+
} else {
|
|
34
|
+
console.warn('RNDebugLibs module not available')
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static showDoraemonKit() {
|
|
39
|
+
console.log('Calling showDoraemonKit')
|
|
40
|
+
if (RNDebugLibs) {
|
|
41
|
+
RNDebugLibs.showDoraemonKit()
|
|
42
|
+
} else {
|
|
43
|
+
console.warn('RNDebugLibs module not available')
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static hideDoraemonKit() {
|
|
48
|
+
console.log('Calling hideDoraemonKit')
|
|
49
|
+
if (RNDebugLibs) {
|
|
50
|
+
RNDebugLibs.hideDoraemonKit()
|
|
51
|
+
} else {
|
|
52
|
+
console.warn('RNDebugLibs module not available')
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import NativeDebugLibs from '../NativeDebugLibs';
|
|
3
|
+
|
|
4
|
+
// Define available third-party debug libraries
|
|
5
|
+
const availableLibs = [
|
|
6
|
+
{
|
|
7
|
+
id: 'flex',
|
|
8
|
+
name: 'FLEX',
|
|
9
|
+
description: 'In-app debugging and exploration tool for iOS',
|
|
10
|
+
platform: 'ios',
|
|
11
|
+
icon: 'tools',
|
|
12
|
+
actions: [
|
|
13
|
+
{ id: 'showExplorer', label: 'Show Explorer', method: NativeDebugLibs.showExplorer },
|
|
14
|
+
{ id: 'hideExplorer', label: 'Hide Explorer', method: NativeDebugLibs.hideExplorer },
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'doraemonkit',
|
|
19
|
+
name: 'DoraemonKit',
|
|
20
|
+
description: 'A full-featured iOS & Android development assistant',
|
|
21
|
+
platform: 'both',
|
|
22
|
+
icon: 'box',
|
|
23
|
+
actions: [
|
|
24
|
+
{ id: 'showDoraemonKit', label: 'Show DoraemonKit', method: NativeDebugLibs.showDoraemonKit },
|
|
25
|
+
{ id: 'hideDoraemonKit', label: 'Hide DoraemonKit', method: NativeDebugLibs.hideDoraemonKit },
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Get libraries available for current platform
|
|
31
|
+
const getPlatformLibs = () => {
|
|
32
|
+
const currentPlatform = Platform.OS;
|
|
33
|
+
return availableLibs.filter(lib =>
|
|
34
|
+
lib.platform === 'both' || lib.platform === currentPlatform
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Setup function is minimal since we're just presenting UI options
|
|
39
|
+
const setup = () => {
|
|
40
|
+
if (!__DEV__) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// No additional setup needed beyond initialization
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Get data - return available libraries for this platform
|
|
47
|
+
const getData = () => {
|
|
48
|
+
return getPlatformLibs();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Cleanup function (if needed)
|
|
52
|
+
const cleanup = () => {
|
|
53
|
+
// Nothing specific to clean up
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Export the feature factory function
|
|
57
|
+
export const createThirdPartyLibsFeature = () => {
|
|
58
|
+
return {
|
|
59
|
+
name: 'thirdPartyLibs',
|
|
60
|
+
label: 'Debug Libraries',
|
|
61
|
+
setup,
|
|
62
|
+
getData,
|
|
63
|
+
cleanup
|
|
64
|
+
};
|
|
65
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import { createPerformanceFeature} from './features/PerformanceFeature'
|
|
|
4
4
|
import { createConsoleLogFeature } from './features/ConsoleLogFeature'
|
|
5
5
|
import { createZustandLogFeature, zustandLogMiddleware } from './features/ZustandLogFeature'
|
|
6
6
|
import { createNavigationLogFeature, addNavigationLog } from './features/NavigationLogFeature'
|
|
7
|
+
import { createThirdPartyLibsFeature } from './features/ThirdPartyLibsFeature'
|
|
8
|
+
import NativeDebugLibs from './NativeDebugLibs'
|
|
7
9
|
|
|
8
10
|
// Registry mapping feature names (strings) to their creator functions
|
|
9
11
|
const featureRegistry = {
|
|
@@ -12,24 +14,31 @@ const featureRegistry = {
|
|
|
12
14
|
performance: createPerformanceFeature,
|
|
13
15
|
zustand: createZustandLogFeature,
|
|
14
16
|
navigation: createNavigationLogFeature,
|
|
17
|
+
thirdPartyLibs: createThirdPartyLibsFeature,
|
|
15
18
|
// Add other built-in features here
|
|
16
19
|
// 'storage': createStorageFeature,
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
// List of default features (can use strings now)
|
|
20
|
-
const defaultFeatures = ['network', 'console', 'zustand', 'navigation']
|
|
23
|
+
const defaultFeatures = ['network', 'console', 'zustand', 'navigation', 'thirdPartyLibs']
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
26
|
* Initializes and shows the Debug ToolKit panel with specified features.
|
|
24
27
|
* Only runs in development mode (__DEV__ === true).
|
|
25
28
|
* Features can be specified as strings (e.g., 'network') or creator functions.
|
|
26
29
|
* @param {Array<string|Function>} features - Array of feature names (strings) or creator functions. Defaults to standard features.
|
|
30
|
+
* @param {Object} options - Additional options like doraemonProductId for third-party debug libraries
|
|
27
31
|
*/
|
|
28
|
-
export function initializeDebugToolkit(features = defaultFeatures) {
|
|
32
|
+
export function initializeDebugToolkit(features = defaultFeatures, options = {}) {
|
|
29
33
|
|
|
30
34
|
try {
|
|
31
35
|
const debugToolKit = new DebugToolKit();
|
|
32
36
|
|
|
37
|
+
// Initialize third-party debug libraries if configured
|
|
38
|
+
if (options.doraemonProductId) {
|
|
39
|
+
NativeDebugLibs.installDoraemonKit(options.doraemonProductId);
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
features.forEach(featureIdentifier => {
|
|
34
43
|
let feature = null;
|
|
35
44
|
let featureCreator = null;
|
|
@@ -84,6 +93,7 @@ export {
|
|
|
84
93
|
createConsoleLogFeature,
|
|
85
94
|
createZustandLogFeature,
|
|
86
95
|
createNavigationLogFeature,
|
|
96
|
+
createThirdPartyLibsFeature,
|
|
87
97
|
addNavigationLog,
|
|
88
98
|
zustandLogMiddleware, // Export middleware for use in Zustand stores
|
|
89
99
|
featureRegistry
|
|
@@ -20,6 +20,7 @@ import SubViewPerformance from './SubViewPerformance'
|
|
|
20
20
|
import SubViewConsoleLogs from './SubViewConsoleLogs'
|
|
21
21
|
import SubViewZustandLogs from './SubViewZustandLogs'
|
|
22
22
|
import SubViewNavigationLogs from './SubViewNavigationLogs'
|
|
23
|
+
import SubViewThirdPartyLibs from './SubViewThirdPartyLibs'
|
|
23
24
|
const { width: screenWidth, height: screenHeight } = Dimensions.get('window')
|
|
24
25
|
|
|
25
26
|
export default class FloatPanelView extends Component {
|
|
@@ -319,6 +320,10 @@ export default class FloatPanelView extends Component {
|
|
|
319
320
|
if (feature.name === 'navigation') {
|
|
320
321
|
return <SubViewNavigationLogs logs={data} />
|
|
321
322
|
}
|
|
323
|
+
|
|
324
|
+
if (feature.name === 'thirdPartyLibs') {
|
|
325
|
+
return <SubViewThirdPartyLibs libraries={data} />
|
|
326
|
+
}
|
|
322
327
|
|
|
323
328
|
// Generic fallback for other feature types
|
|
324
329
|
return (
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
FlatList,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
TextInput,
|
|
9
|
+
Platform,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
|
|
12
|
+
const SubViewThirdPartyLibs = ({ libraries = [] }) => {
|
|
13
|
+
const [expandedLibs, setExpandedLibs] = useState(new Set());
|
|
14
|
+
const [actionParams, setActionParams] = useState({});
|
|
15
|
+
|
|
16
|
+
// Set all libraries to expanded by default and set default product ID
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
// Create a set of all library IDs to set them as expanded
|
|
19
|
+
const allLibIds = new Set(libraries.map(lib => lib.id));
|
|
20
|
+
setExpandedLibs(allLibIds);
|
|
21
|
+
|
|
22
|
+
// Initialize default product ID for all actions that might need it
|
|
23
|
+
const defaultParams = {};
|
|
24
|
+
libraries.forEach(lib => {
|
|
25
|
+
lib.actions.forEach(action => {
|
|
26
|
+
if (action.hasParam) {
|
|
27
|
+
defaultParams[`${lib.id}_${action.id}`] = 'default';
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
setActionParams(defaultParams);
|
|
32
|
+
}, [libraries]);
|
|
33
|
+
|
|
34
|
+
// Handle lib expansion/collapse
|
|
35
|
+
const toggleLibExpand = (libId) => {
|
|
36
|
+
setExpandedLibs(prev => {
|
|
37
|
+
const newSet = new Set(prev);
|
|
38
|
+
if (newSet.has(libId)) {
|
|
39
|
+
newSet.delete(libId);
|
|
40
|
+
} else {
|
|
41
|
+
newSet.add(libId);
|
|
42
|
+
}
|
|
43
|
+
return newSet;
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Execute library action
|
|
48
|
+
const executeAction = (action, libId) => {
|
|
49
|
+
try {
|
|
50
|
+
if (action.hasParam) {
|
|
51
|
+
// Get parameter value (if needed)
|
|
52
|
+
const paramValue = actionParams[`${libId}_${action.id}`] || 'default';
|
|
53
|
+
action.method(paramValue);
|
|
54
|
+
} else {
|
|
55
|
+
action.method();
|
|
56
|
+
}
|
|
57
|
+
// No alerts shown as per requirement
|
|
58
|
+
} catch (error) {
|
|
59
|
+
// Silent error handling as per requirement
|
|
60
|
+
console.error(`Failed to execute ${action.label}:`, error);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Handle param input change
|
|
65
|
+
const handleParamChange = (libId, actionId, value) => {
|
|
66
|
+
setActionParams({
|
|
67
|
+
...actionParams,
|
|
68
|
+
[`${libId}_${actionId}`]: value,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Render a single library card
|
|
73
|
+
const renderLibraryItem = ({ item }) => {
|
|
74
|
+
const isExpanded = expandedLibs.has(item.id);
|
|
75
|
+
const isPlatformSupported = item.platform === 'both' ||
|
|
76
|
+
item.platform === Platform.OS;
|
|
77
|
+
|
|
78
|
+
if (!isPlatformSupported) return null;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<View style={styles.libraryCard}>
|
|
82
|
+
<TouchableOpacity
|
|
83
|
+
style={styles.libraryHeader}
|
|
84
|
+
onPress={() => toggleLibExpand(item.id)}>
|
|
85
|
+
<View style={styles.libraryTitle}>
|
|
86
|
+
<Text style={styles.libraryName}>{item.name}</Text>
|
|
87
|
+
<Text style={styles.platformBadge}>
|
|
88
|
+
{item.platform === 'both' ? 'iOS & Android' : item.platform}
|
|
89
|
+
</Text>
|
|
90
|
+
</View>
|
|
91
|
+
<Text style={styles.expandIcon}>{isExpanded ? '▼' : '▶'}</Text>
|
|
92
|
+
</TouchableOpacity>
|
|
93
|
+
|
|
94
|
+
<Text style={styles.libraryDescription}>{item.description}</Text>
|
|
95
|
+
|
|
96
|
+
{isExpanded && (
|
|
97
|
+
<View style={styles.actionsContainer}>
|
|
98
|
+
{item.actions.map((action) => (
|
|
99
|
+
<View key={action.id} style={styles.actionItem}>
|
|
100
|
+
{action.hasParam && (
|
|
101
|
+
<TextInput
|
|
102
|
+
style={styles.paramInput}
|
|
103
|
+
placeholder={action.paramPlaceholder || 'Parameter'}
|
|
104
|
+
value={actionParams[`${item.id}_${action.id}`] || 'default'}
|
|
105
|
+
onChangeText={(text) =>
|
|
106
|
+
handleParamChange(item.id, action.id, text)
|
|
107
|
+
}
|
|
108
|
+
/>
|
|
109
|
+
)}
|
|
110
|
+
<TouchableOpacity
|
|
111
|
+
style={styles.actionButton}
|
|
112
|
+
onPress={() => executeAction(action, item.id)}>
|
|
113
|
+
<Text style={styles.actionButtonText}>{action.label}</Text>
|
|
114
|
+
</TouchableOpacity>
|
|
115
|
+
</View>
|
|
116
|
+
))}
|
|
117
|
+
</View>
|
|
118
|
+
)}
|
|
119
|
+
</View>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Filter platform-supported libraries
|
|
124
|
+
const supportedLibraries = libraries.filter(
|
|
125
|
+
lib => lib.platform === 'both' || lib.platform === Platform.OS
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<View style={styles.container}>
|
|
130
|
+
{supportedLibraries.length === 0 ? (
|
|
131
|
+
<Text style={styles.emptyText}>
|
|
132
|
+
No debug libraries available for this platform
|
|
133
|
+
</Text>
|
|
134
|
+
) : (
|
|
135
|
+
<FlatList
|
|
136
|
+
data={supportedLibraries}
|
|
137
|
+
renderItem={renderLibraryItem}
|
|
138
|
+
keyExtractor={(item) => item.id}
|
|
139
|
+
contentContainerStyle={styles.listContent}
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
</View>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const styles = StyleSheet.create({
|
|
147
|
+
container: {
|
|
148
|
+
flex: 1,
|
|
149
|
+
backgroundColor: '#fff',
|
|
150
|
+
},
|
|
151
|
+
listContent: {
|
|
152
|
+
padding: 12,
|
|
153
|
+
},
|
|
154
|
+
emptyText: {
|
|
155
|
+
textAlign: 'center',
|
|
156
|
+
color: '#999',
|
|
157
|
+
marginTop: 20,
|
|
158
|
+
fontSize: 16,
|
|
159
|
+
},
|
|
160
|
+
libraryCard: {
|
|
161
|
+
backgroundColor: '#f8f9fa',
|
|
162
|
+
borderRadius: 8,
|
|
163
|
+
borderWidth: 1,
|
|
164
|
+
borderColor: '#e9ecef',
|
|
165
|
+
marginBottom: 16,
|
|
166
|
+
padding: 12,
|
|
167
|
+
elevation: 1,
|
|
168
|
+
shadowColor: '#000',
|
|
169
|
+
shadowOffset: { width: 0, height: 1 },
|
|
170
|
+
shadowOpacity: 0.1,
|
|
171
|
+
shadowRadius: 1,
|
|
172
|
+
},
|
|
173
|
+
libraryHeader: {
|
|
174
|
+
flexDirection: 'row',
|
|
175
|
+
justifyContent: 'space-between',
|
|
176
|
+
alignItems: 'center',
|
|
177
|
+
},
|
|
178
|
+
libraryTitle: {
|
|
179
|
+
flexDirection: 'row',
|
|
180
|
+
alignItems: 'center',
|
|
181
|
+
flex: 1,
|
|
182
|
+
},
|
|
183
|
+
libraryName: {
|
|
184
|
+
fontSize: 18,
|
|
185
|
+
fontWeight: 'bold',
|
|
186
|
+
color: '#333',
|
|
187
|
+
marginRight: 8,
|
|
188
|
+
},
|
|
189
|
+
platformBadge: {
|
|
190
|
+
fontSize: 12,
|
|
191
|
+
color: '#666',
|
|
192
|
+
backgroundColor: '#e9ecef',
|
|
193
|
+
paddingHorizontal: 8,
|
|
194
|
+
paddingVertical: 2,
|
|
195
|
+
borderRadius: 12,
|
|
196
|
+
overflow: 'hidden',
|
|
197
|
+
},
|
|
198
|
+
expandIcon: {
|
|
199
|
+
fontSize: 14,
|
|
200
|
+
color: '#666',
|
|
201
|
+
},
|
|
202
|
+
libraryDescription: {
|
|
203
|
+
marginTop: 8,
|
|
204
|
+
marginBottom: 12,
|
|
205
|
+
color: '#666',
|
|
206
|
+
fontSize: 14,
|
|
207
|
+
lineHeight: 20,
|
|
208
|
+
},
|
|
209
|
+
actionsContainer: {
|
|
210
|
+
marginTop: 8,
|
|
211
|
+
borderTopWidth: 1,
|
|
212
|
+
borderTopColor: '#eee',
|
|
213
|
+
paddingTop: 12,
|
|
214
|
+
},
|
|
215
|
+
actionItem: {
|
|
216
|
+
marginBottom: 8,
|
|
217
|
+
},
|
|
218
|
+
paramInput: {
|
|
219
|
+
borderWidth: 1,
|
|
220
|
+
borderColor: '#ddd',
|
|
221
|
+
borderRadius: 4,
|
|
222
|
+
padding: 8,
|
|
223
|
+
marginBottom: 8,
|
|
224
|
+
fontSize: 14,
|
|
225
|
+
},
|
|
226
|
+
actionButton: {
|
|
227
|
+
backgroundColor: '#0D96F2',
|
|
228
|
+
padding: 10,
|
|
229
|
+
borderRadius: 4,
|
|
230
|
+
alignItems: 'center',
|
|
231
|
+
},
|
|
232
|
+
actionButtonText: {
|
|
233
|
+
color: '#fff',
|
|
234
|
+
fontWeight: '500',
|
|
235
|
+
fontSize: 14,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
export default SubViewThirdPartyLibs;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-debug-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "A simple yet powerful debugging toolkit for React Native with a convenient floating UI for development",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
|
+
"podspec": "react-native-debug-toolkit.podspec",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
10
|
"bundle": "react-native bundle --platform ios --dev false --entry-file index.js --bundle-output dist/main.jsbundle --assets-dest dist"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
3
|
+
|
|
4
|
+
Pod::Spec.new do |s|
|
|
5
|
+
s.name = "react-native-debug-toolkit"
|
|
6
|
+
s.version = package['version']
|
|
7
|
+
s.summary = package['description']
|
|
8
|
+
s.homepage = package['repository']['url']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.author = package['author']
|
|
11
|
+
s.platform = :ios, "11.0"
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => "#{s.version}" }
|
|
13
|
+
s.source_files = "ios/**/*.{h,m}"
|
|
14
|
+
|
|
15
|
+
s.dependency "React-Core"
|
|
16
|
+
|
|
17
|
+
# FLEX is only needed for debug builds
|
|
18
|
+
s.dependency "FLEX", "~> 5.0"
|
|
19
|
+
|
|
20
|
+
# DoraemonKit is only needed for debug builds
|
|
21
|
+
s.dependency "DoraemonKit/Core", "~> 3.0"
|
|
22
|
+
|
|
23
|
+
# This ensures FLEX and DoraemonKit are only included in debug builds
|
|
24
|
+
s.pod_target_xcconfig = { 'OTHER_CFLAGS' => '-DDebug=$(CONFIGURATION)' }
|
|
25
|
+
end
|
package/react-native.config.js
CHANGED
|
@@ -2,4 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
// Let React Native's auto-linking handle all dependencies normally
|
|
5
|
+
dependencies: {
|
|
6
|
+
"react-native-debug-toolkit": {
|
|
7
|
+
platforms: {
|
|
8
|
+
ios: {
|
|
9
|
+
podspecPath: "./react-native-debug-toolkit.podspec",
|
|
10
|
+
sourceDir: "./ios"
|
|
11
|
+
},
|
|
12
|
+
android: {
|
|
13
|
+
sourceDir: "./android"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
};
|