@multiplayer-app/session-recorder-react-native 0.0.1-beta.5 → 0.0.1-beta.6
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/android/src/main/java/com/multiplayer/sessionrecorder/SessionRecorderModule.kt +1 -1
- package/dist/native/SessionRecorderNative.js +1 -1
- package/dist/native/SessionRecorderNative.js.map +1 -1
- package/dist/services/screenMaskingService.js +1 -1
- package/dist/services/screenMaskingService.js.map +1 -1
- package/dist/utils/nativeModuleTest.d.ts +8 -0
- package/dist/utils/nativeModuleTest.js +1 -0
- package/dist/utils/nativeModuleTest.js.map +1 -0
- package/docs/TROUBLESHOOTING.md +168 -0
- package/ios/SessionRecorder.m +1 -1
- package/ios/SessionRecorder.podspec +1 -1
- package/ios/SessionRecorder.swift +2 -2
- package/ios/SessionRecorderNative.podspec +21 -0
- package/package.json +2 -2
- package/react-native.config.js +1 -1
- package/src/native/SessionRecorderNative.ts +5 -5
- package/src/services/screenMaskingService.ts +4 -0
- package/src/utils/nativeModuleTest.ts +60 -0
|
@@ -12,7 +12,7 @@ import java.io.ByteArrayOutputStream
|
|
|
12
12
|
class SessionRecorderModule(reactContext: ReactApplicationContext) :
|
|
13
13
|
ReactContextBaseJavaModule(reactContext) {
|
|
14
14
|
|
|
15
|
-
override fun getName() = "
|
|
15
|
+
override fun getName() = "SessionRecorderNative"
|
|
16
16
|
|
|
17
17
|
@ReactMethod
|
|
18
18
|
fun captureAndMask(promise: Promise) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=void 0;var _reactNative=require("react-native");var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=void 0;var _reactNative=require("react-native");var SessionRecorderNative=_reactNative.NativeModules.SessionRecorderNative;if(!SessionRecorderNative){console.warn('SessionRecorderNative module is not available. Auto-linking may not have completed yet.');}var _default=exports["default"]=SessionRecorderNative;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecorderNative.js","sourceRoot":"","sources":["../../src/native/SessionRecorderNative.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAyB5C,wBAAwB;AACxB,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"SessionRecorderNative.js","sourceRoot":"","sources":["../../src/native/SessionRecorderNative.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAyB5C,wBAAwB;AACxB,MAAM,EAAE,qBAAqB,EAAE,GAAG,aAAa,CAAA;AAE/C,+CAA+C;AAC/C,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,yFAAyF,CAAC,CAAA;AACzG,CAAC;AAED,eAAe,qBAAoD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.screenMaskingService=exports.ScreenMaskingService=void 0;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator"));var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _SessionRecorderNative=_interopRequireDefault(require("../native/SessionRecorderNative"));var _utils=require("../utils");function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var ScreenMaskingService=exports.ScreenMaskingService=function(){function ScreenMaskingService(){var config=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{enabled:true,inputMasking:true};(0,_classCallCheck2["default"])(this,ScreenMaskingService);this.isAvailable=false;this.config=config;this.checkAvailability();}return(0,_createClass2["default"])(ScreenMaskingService,[{key:"checkAvailability",value:function checkAvailability(){var _this=this;try{if(_SessionRecorderNative["default"]&&typeof _SessionRecorderNative["default"].captureAndMask==='function'){this.isAvailable=true;_utils.logger.info('ScreenMaskingService','Screen masking native module is available');}else{this.isAvailable=false;_utils.logger.warn('ScreenMaskingService','Screen masking native module is not available - auto-linking may still be in progress');setTimeout(function(){_this.checkAvailability();},2000);}}catch(error){this.isAvailable=false;_utils.logger.error('ScreenMaskingService','Error checking screen masking availability:',error);}}},{key:"captureMaskedScreen",value:(function(){var _captureMaskedScreen=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee(options){var maskingOptions,maskedImageBase64,_t;return _regenerator["default"].wrap(function(_context){while(1)switch(_context.prev=_context.next){case 0:if(!(!this.isAvailable||!this.config.enabled)){_context.next=1;break;}_utils.logger.warn('ScreenMaskingService','Screen masking is not available or disabled');return _context.abrupt("return",null);case 1:_context.prev=1;maskingOptions=_objectSpread(_objectSpread(_objectSpread({},this.config.defaultOptions),options),{},{inputMasking:this.config.inputMasking});_context.next=2;return _SessionRecorderNative["default"].captureAndMaskWithOptions(maskingOptions);case 2:maskedImageBase64=_context.sent;_utils.logger.info('ScreenMaskingService','Successfully captured masked screen');return _context.abrupt("return",maskedImageBase64);case 3:_context.prev=3;_t=_context["catch"](1);_utils.logger.error('ScreenMaskingService','Failed to capture masked screen:',_t);return _context.abrupt("return",null);case 4:case"end":return _context.stop();}},_callee,this,[[1,3]]);}));function captureMaskedScreen(_x){return _captureMaskedScreen.apply(this,arguments);}return captureMaskedScreen;}())},{key:"captureMaskedScreenBasic",value:(function(){var _captureMaskedScreenBasic=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee2(){var maskedImageBase64,_t2;return _regenerator["default"].wrap(function(_context2){while(1)switch(_context2.prev=_context2.next){case 0:if(!(!this.isAvailable||!this.config.enabled)){_context2.next=1;break;}_utils.logger.warn('ScreenMaskingService','Screen masking is not available or disabled');return _context2.abrupt("return",null);case 1:_context2.prev=1;_context2.next=2;return _SessionRecorderNative["default"].captureAndMask();case 2:maskedImageBase64=_context2.sent;_utils.logger.info('ScreenMaskingService','Successfully captured masked screen (basic)');return _context2.abrupt("return",maskedImageBase64);case 3:_context2.prev=3;_t2=_context2["catch"](1);_utils.logger.error('ScreenMaskingService','Failed to capture masked screen (basic):',_t2);return _context2.abrupt("return",null);case 4:case"end":return _context2.stop();}},_callee2,this,[[1,3]]);}));function captureMaskedScreenBasic(){return _captureMaskedScreenBasic.apply(this,arguments);}return captureMaskedScreenBasic;}())},{key:"updateConfig",value:function updateConfig(config){this.config=_objectSpread(_objectSpread({},this.config),config);_utils.logger.info('ScreenMaskingService','Screen masking configuration updated');}},{key:"isScreenMaskingAvailable",value:function isScreenMaskingAvailable(){return this.isAvailable&&this.config.enabled;}},{key:"getConfig",value:function getConfig(){return _objectSpread({},this.config);}}]);}();var screenMaskingService=exports.screenMaskingService=new ScreenMaskingService();
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.screenMaskingService=exports.ScreenMaskingService=void 0;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator"));var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _SessionRecorderNative=_interopRequireDefault(require("../native/SessionRecorderNative"));var _utils=require("../utils");var _nativeModuleTest=require("../utils/nativeModuleTest");function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var ScreenMaskingService=exports.ScreenMaskingService=function(){function ScreenMaskingService(){var config=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{enabled:true,inputMasking:true};(0,_classCallCheck2["default"])(this,ScreenMaskingService);this.isAvailable=false;this.config=config;this.checkAvailability();}return(0,_createClass2["default"])(ScreenMaskingService,[{key:"checkAvailability",value:function checkAvailability(){var _this=this;try{if(_SessionRecorderNative["default"]&&typeof _SessionRecorderNative["default"].captureAndMask==='function'){this.isAvailable=true;_utils.logger.info('ScreenMaskingService','Screen masking native module is available');}else{this.isAvailable=false;_utils.logger.warn('ScreenMaskingService','Screen masking native module is not available - auto-linking may still be in progress');(0,_nativeModuleTest.testNativeModuleAvailability)();setTimeout(function(){_this.checkAvailability();},2000);}}catch(error){this.isAvailable=false;_utils.logger.error('ScreenMaskingService','Error checking screen masking availability:',error);}}},{key:"captureMaskedScreen",value:(function(){var _captureMaskedScreen=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee(options){var maskingOptions,maskedImageBase64,_t;return _regenerator["default"].wrap(function(_context){while(1)switch(_context.prev=_context.next){case 0:if(!(!this.isAvailable||!this.config.enabled)){_context.next=1;break;}_utils.logger.warn('ScreenMaskingService','Screen masking is not available or disabled');return _context.abrupt("return",null);case 1:_context.prev=1;maskingOptions=_objectSpread(_objectSpread(_objectSpread({},this.config.defaultOptions),options),{},{inputMasking:this.config.inputMasking});_context.next=2;return _SessionRecorderNative["default"].captureAndMaskWithOptions(maskingOptions);case 2:maskedImageBase64=_context.sent;_utils.logger.info('ScreenMaskingService','Successfully captured masked screen');return _context.abrupt("return",maskedImageBase64);case 3:_context.prev=3;_t=_context["catch"](1);_utils.logger.error('ScreenMaskingService','Failed to capture masked screen:',_t);return _context.abrupt("return",null);case 4:case"end":return _context.stop();}},_callee,this,[[1,3]]);}));function captureMaskedScreen(_x){return _captureMaskedScreen.apply(this,arguments);}return captureMaskedScreen;}())},{key:"captureMaskedScreenBasic",value:(function(){var _captureMaskedScreenBasic=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee2(){var maskedImageBase64,_t2;return _regenerator["default"].wrap(function(_context2){while(1)switch(_context2.prev=_context2.next){case 0:if(!(!this.isAvailable||!this.config.enabled)){_context2.next=1;break;}_utils.logger.warn('ScreenMaskingService','Screen masking is not available or disabled');return _context2.abrupt("return",null);case 1:_context2.prev=1;_context2.next=2;return _SessionRecorderNative["default"].captureAndMask();case 2:maskedImageBase64=_context2.sent;_utils.logger.info('ScreenMaskingService','Successfully captured masked screen (basic)');return _context2.abrupt("return",maskedImageBase64);case 3:_context2.prev=3;_t2=_context2["catch"](1);_utils.logger.error('ScreenMaskingService','Failed to capture masked screen (basic):',_t2);return _context2.abrupt("return",null);case 4:case"end":return _context2.stop();}},_callee2,this,[[1,3]]);}));function captureMaskedScreenBasic(){return _captureMaskedScreenBasic.apply(this,arguments);}return captureMaskedScreenBasic;}())},{key:"updateConfig",value:function updateConfig(config){this.config=_objectSpread(_objectSpread({},this.config),config);_utils.logger.info('ScreenMaskingService','Screen masking configuration updated');}},{key:"isScreenMaskingAvailable",value:function isScreenMaskingAvailable(){return this.isAvailable&&this.config.enabled;}},{key:"getConfig",value:function getConfig(){return _objectSpread({},this.config);}}]);}();var screenMaskingService=exports.screenMaskingService=new ScreenMaskingService();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenMaskingService.js","sourceRoot":"","sources":["../../src/services/screenMaskingService.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAyC,MAAM,iCAAiC,CAAA;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"screenMaskingService.js","sourceRoot":"","sources":["../../src/services/screenMaskingService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.testAutoLinkingConfig=testAutoLinkingConfig;exports.testNativeModuleAvailability=testNativeModuleAvailability;var _reactNative=require("react-native");var _logger=require("./logger");function testNativeModuleAvailability(){_logger.logger.info('NativeModuleTest','Testing native module availability...');var availableModules=Object.keys(_reactNative.NativeModules);_logger.logger.info('NativeModuleTest',"Available native modules: ".concat(availableModules.join(', ')));var SessionRecorderNative=_reactNative.NativeModules.SessionRecorderNative;if(SessionRecorderNative){_logger.logger.info('NativeModuleTest','✅ SessionRecorderNative module is available!');if(typeof SessionRecorderNative.captureAndMask==='function'){_logger.logger.info('NativeModuleTest','✅ captureAndMask method is available!');}else{_logger.logger.warn('NativeModuleTest','❌ captureAndMask method is not available');}if(typeof SessionRecorderNative.captureAndMaskWithOptions==='function'){_logger.logger.info('NativeModuleTest','✅ captureAndMaskWithOptions method is available!');}else{_logger.logger.warn('NativeModuleTest','❌ captureAndMaskWithOptions method is not available');}}else{_logger.logger.error('NativeModuleTest','❌ SessionRecorderNative module is not available');_logger.logger.info('NativeModuleTest','This could mean:');_logger.logger.info('NativeModuleTest','1. Auto-linking has not completed yet');_logger.logger.info('NativeModuleTest','2. The native module was not properly built');_logger.logger.info('NativeModuleTest','3. The module name does not match');}}function testAutoLinkingConfig(){_logger.logger.info('NativeModuleTest','Testing auto-linking configuration...');try{var config=require('../../react-native.config.js');_logger.logger.info('NativeModuleTest','✅ react-native.config.js found');if(config.dependencies&&config.dependencies['react-native-session-recorder']){_logger.logger.info('NativeModuleTest','✅ Auto-linking configuration found for react-native-session-recorder');}else{_logger.logger.warn('NativeModuleTest','❌ Auto-linking configuration not found for react-native-session-recorder');}}catch(error){_logger.logger.warn('NativeModuleTest','❌ react-native.config.js not found or invalid');}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativeModuleTest.js","sourceRoot":"","sources":["../../src/utils/nativeModuleTest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC;;GAEG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAA;IAExE,mCAAmC;IACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACnD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,6BAA6B,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAE3F,+CAA+C;IAC/C,MAAM,EAAE,qBAAqB,EAAE,GAAG,aAAa,CAAA;IAE/C,IAAI,qBAAqB,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,8CAA8C,CAAC,CAAA;QAE/E,4BAA4B;QAC5B,IAAI,OAAO,qBAAqB,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YAC/D,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAA;QAC1E,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,0CAA0C,CAAC,CAAA;QAC7E,CAAC;QAED,IAAI,OAAO,qBAAqB,CAAC,yBAAyB,KAAK,UAAU,EAAE,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,kDAAkD,CAAC,CAAA;QACrF,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,qDAAqD,CAAC,CAAA;QACxF,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,iDAAiD,CAAC,CAAA;QACnF,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAA;QACnD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAA;QACxE,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,6CAA6C,CAAC,CAAA;QAC9E,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,mCAAmC,CAAC,CAAA;IACtE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAA;IAExE,oEAAoE;IACpE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAA;QACtD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,gCAAgC,CAAC,CAAA;QAEjE,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,+BAA+B,CAAC,EAAE,CAAC;YAChF,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,sEAAsE,CAAC,CAAA;QACzG,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,0EAA0E,CAAC,CAAA;QAC7G,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,+CAA+C,CAAC,CAAA;IAClF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Troubleshooting Native Module Issues
|
|
2
|
+
|
|
3
|
+
If you're seeing the warning "Screen masking native module is not available - auto-linking may still be in progress", follow these steps:
|
|
4
|
+
|
|
5
|
+
## Quick Fix
|
|
6
|
+
|
|
7
|
+
1. **Clean and Rebuild**:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Clean React Native cache
|
|
11
|
+
npx react-native start --reset-cache
|
|
12
|
+
|
|
13
|
+
# For iOS
|
|
14
|
+
cd ios && pod install && cd ..
|
|
15
|
+
npx react-native run-ios
|
|
16
|
+
|
|
17
|
+
# For Android
|
|
18
|
+
npx react-native run-android
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **Check Auto-Linking**:
|
|
22
|
+
```bash
|
|
23
|
+
# Check if auto-linking detected the module
|
|
24
|
+
npx react-native config
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Detailed Troubleshooting
|
|
28
|
+
|
|
29
|
+
### 1. Verify Package Installation
|
|
30
|
+
|
|
31
|
+
Make sure the package is properly installed:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm list @multiplayer-app/session-recorder-react-native
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Check Native Module Registration
|
|
38
|
+
|
|
39
|
+
The native module should be named `SessionRecorderNative`. You can verify this by checking the logs for:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Available native modules: [..., SessionRecorderNative, ...]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. iOS Specific Issues
|
|
46
|
+
|
|
47
|
+
**Check Podfile**:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
# In your ios/Podfile, you should see:
|
|
51
|
+
pod 'SessionRecorderNative', :path => '../node_modules/@multiplayer-app/session-recorder-react-native/ios'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Clean iOS Build**:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd ios
|
|
58
|
+
rm -rf build
|
|
59
|
+
rm -rf Pods
|
|
60
|
+
rm Podfile.lock
|
|
61
|
+
pod install
|
|
62
|
+
cd ..
|
|
63
|
+
npx react-native run-ios
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 4. Android Specific Issues
|
|
67
|
+
|
|
68
|
+
**Check MainApplication.java**:
|
|
69
|
+
|
|
70
|
+
```java
|
|
71
|
+
// Should be automatically added by auto-linking:
|
|
72
|
+
import com.multiplayer.sessionrecorder.SessionRecorderPackage;
|
|
73
|
+
|
|
74
|
+
// In getPackages():
|
|
75
|
+
new SessionRecorderPackage()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Clean Android Build**:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd android
|
|
82
|
+
./gradlew clean
|
|
83
|
+
cd ..
|
|
84
|
+
npx react-native run-android
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 5. Manual Linking (If Auto-Linking Fails)
|
|
88
|
+
|
|
89
|
+
If auto-linking doesn't work, you can manually link:
|
|
90
|
+
|
|
91
|
+
**iOS**:
|
|
92
|
+
|
|
93
|
+
1. Add to `ios/Podfile`:
|
|
94
|
+
```ruby
|
|
95
|
+
pod 'SessionRecorderNative', :path => '../node_modules/@multiplayer-app/session-recorder-react-native/ios'
|
|
96
|
+
```
|
|
97
|
+
2. Run `pod install`
|
|
98
|
+
|
|
99
|
+
**Android**:
|
|
100
|
+
|
|
101
|
+
1. Add to `android/settings.gradle`:
|
|
102
|
+
```gradle
|
|
103
|
+
include ':react-native-session-recorder'
|
|
104
|
+
project(':react-native-session-recorder').projectDir = new File(rootProject.projectDir, '../node_modules/@multiplayer-app/session-recorder-react-native/android')
|
|
105
|
+
```
|
|
106
|
+
2. Add to `android/app/build.gradle`:
|
|
107
|
+
```gradle
|
|
108
|
+
dependencies {
|
|
109
|
+
implementation project(':react-native-session-recorder')
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
3. Add to `MainApplication.java`:
|
|
113
|
+
|
|
114
|
+
```java
|
|
115
|
+
import com.multiplayer.sessionrecorder.SessionRecorderPackage;
|
|
116
|
+
|
|
117
|
+
@Override
|
|
118
|
+
protected List<ReactPackage> getPackages() {
|
|
119
|
+
return Arrays.<ReactPackage>asList(
|
|
120
|
+
new MainReactPackage(),
|
|
121
|
+
new SessionRecorderPackage()
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 6. Debug Native Module Availability
|
|
127
|
+
|
|
128
|
+
Add this to your app to debug:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { testNativeModuleAvailability } from '@multiplayer-app/session-recorder-react-native/utils'
|
|
132
|
+
|
|
133
|
+
// Call this in your app
|
|
134
|
+
testNativeModuleAvailability()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This will log detailed information about native module availability.
|
|
138
|
+
|
|
139
|
+
### 7. Common Issues
|
|
140
|
+
|
|
141
|
+
**Issue**: "Module not found" error
|
|
142
|
+
**Solution**: Ensure the package is installed and auto-linking is working
|
|
143
|
+
|
|
144
|
+
**Issue**: "Method not available" error
|
|
145
|
+
**Solution**: The native module is linked but methods aren't exposed. Check the native code.
|
|
146
|
+
|
|
147
|
+
**Issue**: Auto-linking not working
|
|
148
|
+
**Solution**: Check `react-native.config.js` and ensure React Native version is 0.60+
|
|
149
|
+
|
|
150
|
+
**Issue**: Pod install fails
|
|
151
|
+
**Solution**: Update CocoaPods: `sudo gem install cocoapods`
|
|
152
|
+
|
|
153
|
+
### 8. Verification
|
|
154
|
+
|
|
155
|
+
Once fixed, you should see:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
✅ SessionRecorderNative module is available!
|
|
159
|
+
✅ captureAndMask method is available!
|
|
160
|
+
✅ captureAndMaskWithOptions method is available!
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Still Having Issues?
|
|
164
|
+
|
|
165
|
+
1. Check the [React Native Auto-Linking documentation](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md)
|
|
166
|
+
2. Verify your React Native version (0.60+ required)
|
|
167
|
+
3. Check for conflicting native modules
|
|
168
|
+
4. Try creating a fresh React Native project and testing the module there
|
package/ios/SessionRecorder.m
CHANGED
|
@@ -3,7 +3,7 @@ require "json"
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
|
|
4
4
|
|
|
5
5
|
Pod::Spec.new do |s|
|
|
6
|
-
s.name = "
|
|
6
|
+
s.name = "SessionRecorderNative"
|
|
7
7
|
s.version = package["version"]
|
|
8
8
|
s.summary = "Native session recorder module for React Native"
|
|
9
9
|
s.description = "A native module that provides session recording with automatic masking of sensitive UI elements"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
import React
|
|
3
3
|
|
|
4
|
-
@objc(
|
|
5
|
-
class
|
|
4
|
+
@objc(SessionRecorderNative)
|
|
5
|
+
class SessionRecorderNative: NSObject {
|
|
6
6
|
|
|
7
7
|
@objc func captureAndMask(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
8
8
|
DispatchQueue.main.async {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "SessionRecorderNative"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = "Native session recorder module for React Native"
|
|
9
|
+
s.description = "A native module that provides session recording with automatic masking of sensitive UI elements"
|
|
10
|
+
s.homepage = "https://github.com/multiplayer-app/multiplayer-session-recorder-javascript"
|
|
11
|
+
s.license = "MIT"
|
|
12
|
+
s.authors = { "Multiplayer Software, Inc." => "https://www.multiplayer.app" }
|
|
13
|
+
s.platforms = { :ios => "12.0" }
|
|
14
|
+
s.source = { :git => "https://github.com/multiplayer-app/multiplayer-session-recorder-javascript.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
s.requires_arc = true
|
|
18
|
+
|
|
19
|
+
s.dependency "React-Core"
|
|
20
|
+
s.dependency "React"
|
|
21
|
+
end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplayer-app/session-recorder-react-native",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.6",
|
|
4
4
|
"description": "Multiplayer Fullstack Session Recorder for React Native",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Multiplayer Software, Inc.",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
},
|
|
92
92
|
"react-native": {
|
|
93
93
|
"ios": {
|
|
94
|
-
"podspecPath": "./ios/
|
|
94
|
+
"podspecPath": "./ios/SessionRecorderNative.podspec"
|
|
95
95
|
},
|
|
96
96
|
"android": {
|
|
97
97
|
"sourceDir": "./android",
|
package/react-native.config.js
CHANGED
|
@@ -14,7 +14,7 @@ export interface SessionRecorderNativeModule {
|
|
|
14
14
|
* @returns Promise that resolves to base64 encoded image
|
|
15
15
|
*/
|
|
16
16
|
captureAndMask(): Promise<string>
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
/**
|
|
19
19
|
* Capture the current screen and apply masking with custom options
|
|
20
20
|
* @param options Custom masking options
|
|
@@ -24,11 +24,11 @@ export interface SessionRecorderNativeModule {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Get the native module
|
|
27
|
-
const {
|
|
27
|
+
const { SessionRecorderNative } = NativeModules
|
|
28
28
|
|
|
29
29
|
// Validate that the native module is available
|
|
30
|
-
if (!
|
|
31
|
-
console.warn('
|
|
30
|
+
if (!SessionRecorderNative) {
|
|
31
|
+
console.warn('SessionRecorderNative module is not available. Auto-linking may not have completed yet.')
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export default
|
|
34
|
+
export default SessionRecorderNative as SessionRecorderNativeModule
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import SessionRecorderNative, { MaskingOptions } from '../native/SessionRecorderNative'
|
|
2
2
|
import { logger } from '../utils'
|
|
3
|
+
import { testNativeModuleAvailability } from '../utils/nativeModuleTest'
|
|
3
4
|
|
|
4
5
|
export interface ScreenMaskingConfig {
|
|
5
6
|
/** Whether screen masking is enabled */
|
|
@@ -32,6 +33,9 @@ export class ScreenMaskingService {
|
|
|
32
33
|
this.isAvailable = false
|
|
33
34
|
logger.warn('ScreenMaskingService', 'Screen masking native module is not available - auto-linking may still be in progress')
|
|
34
35
|
|
|
36
|
+
// Run diagnostic test
|
|
37
|
+
testNativeModuleAvailability()
|
|
38
|
+
|
|
35
39
|
// Retry after a delay for auto-linking
|
|
36
40
|
setTimeout(() => {
|
|
37
41
|
this.checkAvailability()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native'
|
|
2
|
+
import { logger } from './logger'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test function to verify native module availability
|
|
6
|
+
*/
|
|
7
|
+
export function testNativeModuleAvailability(): void {
|
|
8
|
+
logger.info('NativeModuleTest', 'Testing native module availability...')
|
|
9
|
+
|
|
10
|
+
// Log all available native modules
|
|
11
|
+
const availableModules = Object.keys(NativeModules)
|
|
12
|
+
logger.info('NativeModuleTest', `Available native modules: ${availableModules.join(', ')}`)
|
|
13
|
+
|
|
14
|
+
// Check specifically for SessionRecorderNative
|
|
15
|
+
const { SessionRecorderNative } = NativeModules
|
|
16
|
+
|
|
17
|
+
if (SessionRecorderNative) {
|
|
18
|
+
logger.info('NativeModuleTest', '✅ SessionRecorderNative module is available!')
|
|
19
|
+
|
|
20
|
+
// Test if the methods exist
|
|
21
|
+
if (typeof SessionRecorderNative.captureAndMask === 'function') {
|
|
22
|
+
logger.info('NativeModuleTest', '✅ captureAndMask method is available!')
|
|
23
|
+
} else {
|
|
24
|
+
logger.warn('NativeModuleTest', '❌ captureAndMask method is not available')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof SessionRecorderNative.captureAndMaskWithOptions === 'function') {
|
|
28
|
+
logger.info('NativeModuleTest', '✅ captureAndMaskWithOptions method is available!')
|
|
29
|
+
} else {
|
|
30
|
+
logger.warn('NativeModuleTest', '❌ captureAndMaskWithOptions method is not available')
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
logger.error('NativeModuleTest', '❌ SessionRecorderNative module is not available')
|
|
34
|
+
logger.info('NativeModuleTest', 'This could mean:')
|
|
35
|
+
logger.info('NativeModuleTest', '1. Auto-linking has not completed yet')
|
|
36
|
+
logger.info('NativeModuleTest', '2. The native module was not properly built')
|
|
37
|
+
logger.info('NativeModuleTest', '3. The module name does not match')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Test function to verify auto-linking configuration
|
|
43
|
+
*/
|
|
44
|
+
export function testAutoLinkingConfig(): void {
|
|
45
|
+
logger.info('NativeModuleTest', 'Testing auto-linking configuration...')
|
|
46
|
+
|
|
47
|
+
// Check if react-native.config.js exists and is properly configured
|
|
48
|
+
try {
|
|
49
|
+
const config = require('../../react-native.config.js')
|
|
50
|
+
logger.info('NativeModuleTest', '✅ react-native.config.js found')
|
|
51
|
+
|
|
52
|
+
if (config.dependencies && config.dependencies['react-native-session-recorder']) {
|
|
53
|
+
logger.info('NativeModuleTest', '✅ Auto-linking configuration found for react-native-session-recorder')
|
|
54
|
+
} else {
|
|
55
|
+
logger.warn('NativeModuleTest', '❌ Auto-linking configuration not found for react-native-session-recorder')
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.warn('NativeModuleTest', '❌ react-native.config.js not found or invalid')
|
|
59
|
+
}
|
|
60
|
+
}
|