Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-native-sketch-canvas does not support new architecture even with RN v0.72 interop layer #236

Open
karthiktrcapgemini opened this issue Jul 3, 2023 · 17 comments

Comments

@karthiktrcapgemini
Copy link

karthiktrcapgemini commented Jul 3, 2023

Summary

Hi @terrylinla,
We have identified that this library is not working with the RN new architecture. So we have moved forward with RN 0.72.1 to enable this legacy module with the interop layer and new arch as suggested here -> reactwg/react-native-new-architecture#135

Reproducible sample code -

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
} from 'react-native';

import { SketchCanvas } from '@terrylinla/react-native-sketch-canvas';

export default class example extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={{ flex: 1, flexDirection: 'row' }}>
          <SketchCanvas
            style={{ flex: 1 }}
            strokeColor={'red'}
            strokeWidth={7}
          />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF',
  },
});

AppRegistry.registerComponent('example', () => example);

Steps to reproduce

  • yarn add react-native-sketch-canvas
  • cd ios
  • bundle install
  • RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
  • cd ..
  • open android/gradle.properties
  • change the newArchEnabled boolean from false to true
  • Add the component to unstable_reactLegacyComponentNames array in react-native.config.js
  • npx react-native run-ios
  • npx react-native run-android
  • Update the App.js file with the snippet in the Reproducible Sample Code section

Expected result -

  • Module opens and we are able to save the edited sketch

Actual Result -

-Module opens and we are able to add a sketch but then it throws this exception -

Simulator Screenshot - iPhone 14 - 2023-07-03 at 10 56 09

React Native Sketch Canvas Version

0.8.0

What platforms are you seeing the problem on?

Android, iOS

React Native Version

0.72.1

What version of Expo are you using?

Not using Expo

Device(s)

iPhone 14 (iOS 16.4) | Android Pixel 5 (API 33)

Additional information

No response

@ravindraguptacapgemini
Copy link

@cipolleschi can you help here?

@karthiktrcapgemini karthiktrcapgemini changed the title react-native-sketch-canvas does not support new architecture even with 0.72 interop layer react-native-sketch-canvas does not support new architecture even with RN v0.72 interop layer Jul 3, 2023
@cipolleschi
Copy link

@ravindraguptacapgemini @karthiktrcapgemini thanks for testing this.

I don't have an immediate answer, as this error looks a bit hard to identify for me.
Can you prepare a repro using this template?

This will make it easier for us to run it and see what's going wrong. Thank you so much!

cc. @cortinico as this is also failing for Android

@karthiktrcapgemini
Copy link
Author

Sure @cipolleschi, We will share a reproducible repo as soon as possible.

@karthiktrcapgemini
Copy link
Author

karthiktrcapgemini commented Jul 6, 2023

@cipolleschi - Here is the reproducible repo for this -> https://github.com/karthiktrcapgemini/react-native-sketch-canvas-interop-layer-issue

Adding a few more details -

Android -

  • Without adding the component to unstable_reactLegacyComponentNames - Result - Standard "RNSketchCanvas is not fabric compatible yet" red screen is shown
  • After adding the component to unstable_reactLegacyComponentNames - Result - The feature opens but we are unable to sketch, there is no error or exception shown. Nothing happens, its a blank screen with the given background colour to sketch canvas.

Screenshot_1688641461

iOS -

  • Without adding the component to unstable_reactLegacyComponentNames - Result - Standard "RNSketchCanvas is not fabric compatible yet" red screen is shown
  • After adding the component to unstable_reactLegacyComponentNames - Result - We are able to sketch on the canvas but it seems the mechanism to fetch the base64 png image of the sketch is failing at the native code. Please see SS

Simulator Screenshot - iPhone SE (3rd generation) - 2023-07-06 at 07 06 21

Simulator Screenshot - iPhone SE (3rd generation) - 2023-07-06 at 07 02 39

@cipolleschi
Copy link

Thanks for sharing this.
For full transparency, I'm going to be on PTO for some days starting from the next week. I expect to be back and operational from the 19th.
Can this wait before I'm back?

@karthiktrcapgemini
Copy link
Author

karthiktrcapgemini commented Jul 6, 2023

Unfortunately, We are in the process of migrating one of our apps to new arch and this is one of the few blockers we are facing. Any way at all to expedite this or things we could check at our end in the meantime? @cipolleschi

@cipolleschi
Copy link

ok, I found some time to investigate this for iOS.

I think that the root problem is in the logic of how the views are added/removed from the registry.
Right now, we add a view to the legacyView registry right before a command is dispatched and we remove it right after.

The problem is that RNSketchCanvas expect the view to always be in the registry, so it tries to access the registry outside a command invocation (due to some async call) and that fails.

I prepared this PR that should fix the issue on iOS, but we have to wait for @cortinico for Android.

@karthiktrcapgemini
Copy link
Author

Thanks a lot @cipolleschi, this sounds great. I will keep this thread posted once I get a chance to test this fix for iOS

@cipolleschi
Copy link

We are in the process of migrating one of our apps to new arch and this is one of the few blockers we are facing

I just want to highlight a thing. Although I really really appreciate the effort in migrating your app to the New Architecture, and all the feedback that comes with the migration, please remember that the New Architecture is still experimental. There will be breaking changes in the APIs while we work in releasing everything that's needed and there will be new pieces of the Architecture that will arrive in 0.73.

@karthiktrcapgemini
Copy link
Author

Thanks @cipolleschi. Acknowledged.
Also, The fix seems to be working fine for iOS but we will still need a bit more scenario testing on it.
@cortinico - Your inputs for Android would be greatly appreciated.

@ravindraguptacapgemini
Copy link

@cortinico we are getting this issue for multiple component, sketch-canvas is one of them, can you please check the reproducer and see what's breaking thing there. Hope to get your response, thanks.

@cortinico
Copy link

Hi @karthiktrcapgemini @ravindraguptacapgemini
Thanks for sharing a reproducer which helped me understand what was going on.

The problem is with commands & the interop layer. Specifically react-native-sketch-canvas is using receiveCommand(View, int, ReadableArray) here:

public void receiveCommand(SketchCanvas view, int commandType, @Nullable ReadableArray args) {

I would need to wait for @cipolleschi to be back in the office next week to discuss this, but I noticed a change for iOS: facebook/react-native@c7aaae6 is causing all events to be delivered as string, which ends up not delivering those events on this specific component.

We'll investigate further and get back with a fix as this is definitely affecting other libraries.

@karthiktrcapgemini
Copy link
Author

Hi @cortinico Thanks for identifying the RC. Is there a tentative ETA on the PR or version with which the fix for this might be released?

@cortinico
Copy link

Hi @cortinico Thanks for identifying the RC. Is there a tentative ETA on the PR or version with which the fix for this might be released?

Hey @ravindraguptacapgemini @karthiktrcapgemini The fix will be shipped when it's ready

cortinico added a commit to cortinico/react-native that referenced this issue Jul 20, 2023
Summary:
This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Differential Revision: D47600094

fbshipit-source-id: a051eaf145cacaa275f520c46aeea95165f842a0
cortinico added a commit to cortinico/react-native that referenced this issue Jul 20, 2023
Summary:
Pull Request resolved: facebook#38527

This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Reviewed By: cipolleschi

Differential Revision: D47600094

fbshipit-source-id: 73fd3f5bdee860f1d371541b3bd0aa60a62e2981
cortinico added a commit to cortinico/react-native that referenced this issue Jul 21, 2023
Summary:
Pull Request resolved: facebook#38527

This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Reviewed By: cipolleschi

Differential Revision: D47600094

fbshipit-source-id: ee4b4829610c42304bcbf50bd27d2b4093dae760
cortinico added a commit to cortinico/react-native that referenced this issue Jul 21, 2023
Summary:
Pull Request resolved: facebook#38527

This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Reviewed By: cipolleschi

Differential Revision: D47600094

fbshipit-source-id: adb789abc529b9b1aa0dfcf979ac16856a31135d
facebook-github-bot pushed a commit to facebook/react-native that referenced this issue Jul 21, 2023
Summary:
Pull Request resolved: #38527

This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Reviewed By: cipolleschi

Differential Revision: D47600094

fbshipit-source-id: c35f0509e6c6c0cddc7090a069882f92dd95532e
cortinico added a commit to facebook/react-native that referenced this issue Aug 8, 2023
Summary:
Pull Request resolved: #38527

This fixes a bug that got reported for the Fabric Interop for Android with Command dispatching.
(See terrylinla/react-native-sketch-canvas#236)

The problem is that libraries that were receiving commands as ints with:
```
public void receiveCommand(
      int surfaceId, int reactTag, int commandId, Nullable ReadableArray commandArgs) {
```

would not receive command with the Fabric Interop for Android.

The problem is that with Fabric, events are dispatched as string always.
cipolleschi took care of this for iOS, but we realized that the Android part was missing. I'm adding it here.

The logic is, if the event is dispatched as a string that represents a number (say `"42"`) and the user has Fabric Interop enabled, then we dispatch the event as `int` (so libraries will keep on working).

Changelog:
[Android] [Fixed] - Fabric Interop - Properly dispatch integer commands

Reviewed By: cipolleschi

Differential Revision: D47600094

fbshipit-source-id: c35f0509e6c6c0cddc7090a069882f92dd95532e
@karthiktrcapgemini
Copy link
Author

Hi @cortinico, Thanks for releasing the above Android issue fix for this as part of 0.72.4. We have had the chance to test the fix and see an additional issue only with Android. This issue is completely fixed now with iOS with interop layer. Details below -

React Native Version

0.72.4

What platforms are you seeing the problem on?

Android

Device(s)

Android Pixel 5 (API 33)

Issue

We are now able to sketch on the canvas which we were previously unable to do as per our above post. But now, getBase64* method does not return the result base64 we need for the sketch. This works perfectly fine for iOS. Please see SSs below -

*From the Documentation -
getBase64(imageType, transparent, includeImage, cropToImageSize, callback) | Get the base64 of image and receive data in callback function, which called with 2 arguments. First one is error (null if no error) and second one is base64 result.

iOS

Screenshot 2023-08-14 at 8 46 44 AM

Android

Screenshot 2023-08-14 at 8 36 15 AM

Reproducer APP - I have updated the reproducer app to log the base64 result from the method

https://github.com/karthiktrcapgemini/react-native-sketch-canvas-interop-layer-issue

@cortinico
Copy link

Hi @karthiktrcapgemini
Thanks for updating the repro, this allowed me to test really quickly and understand what's the issue.

The problem is that the getBase64 method is implemented differently between Android & iOS:

getBase64(imageType, transparent, includeImage, includeText, cropToImageSize, callback) {
if (Platform.OS === 'ios') {
SketchCanvasManager.transferToBase64(this._handle, imageType, transparent, includeImage, includeText, cropToImageSize, callback)
} else {
NativeModules.SketchCanvasModule.transferToBase64(this._handle, imageType, transparent, includeImage, includeText, cropToImageSize, callback)
}
}

On iOS it delegates the implementation to a method in the ViewManager. On Android instead it uses a separate Native Module.

Calling NativeModules.SketchCanvasModule.(...) is currently not supported on the New Architecture. We're working on providing a Native Module Interop Layer in 0.73 that will most likely fill this gap, but for the time being, this library should be patched to don't do this.

In an ideal world this library should instead fire a command to save to Base64 that the ViewManager can consume and work on.

@iBotPeaches
Copy link

I took a look at a patch for this and I learned that the methods were built differently to workaround getting a value directly from the ViewManager.

So the SketchCanvasModule just grabs the view of the SketchCanvas to call a method off it, in order to return it in a callback.

Based on @cortinico comment - this probably was not the way to do things. I just struggle to figure out if this plugin was always just abusing a method of development or if it should have always hit a command to view manager for it to emit an event back.

Since lets say we make an event/callback on the View manager for like onSave and onBase64. It makes perfect sense for onSave since you are providing output about an operation that completed or didn't.

Saving base64 is just getting an output scalar back, so an async nature of making a command and subscribing to an event (onBase64) seems pretty rough. However, when you consider the current method has to include its own callback in userland - thats also pretty rough.

https://github.com/sourcetoad/react-native-sketch-canvas/blob/master/example/src/App.tsx#L317-L328

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants