Andrei Calazans

React Native Weekly - W28 2021

☕️ 5 min read

Welcome to the 17th edition of React Native Weekly = )

Flutter Vs. React Native Part 3

Last piece of this series, I speculate some elements everyone should consider when deciding which to choose.

I’d love feedback on that post since I am certain it is very opinionated by my experiences.

Upgrade folly to fix NDK 21 build issue (#31802)

Kudo Chien ckchien@gmail.com made a PR upgrading Folly to fix an issue building for NDK 21 on Android.

Fix TouchableNativeFeedback ripple starts on previous touch location (#31777)

From Nishan Bende nishanbende@gmail.com who initially implemented the native ripple support on Android

Issue:

Fix:

Ship Scroll State Update To ScrollView and HorizontalScrollView

Back in week 21/2021 I highlighted a proposed fix from the React Native core team to fix the Scroll state in C++ becoming out of sync with the native component. This caused the measure function to behave unexpectedly.

This commit ships the same solution to the ScrollView and HorizontalScrollView. While it is not perfect, it decreases the likely hood of the it being incorrect.

I wonder if this problem is inherited by the usage of Java Native Interfaces to communicate between C++ and Java?

Add ScrollView.automaticallyAdjustsScrollIndicatorInsets prop (on iOS) (#29809)

Justin Huntington justin@naraorganics.com made a commit explaining the reasoning quite well and further explanations can be found in the original issue 28140

In summary, iOS 13 added a new property UIScrollView: automaticallyAdjustsScrollIndicatorInsets. It changed how the scrollIndicatorsInsets property behaves, when set to YES any scroll insets are added in addition to the device’s safe area, when set to NO it uses the older behavior prior to iOS 13 where these insets did not consider safe area.

The problem with keeping the default value YES is it broke the behavior on prior to iOS 13 devices.

This change sets the default for this property to NO, making the behavior consistent across iOS versions, and allowing developers full control.

You can set this prop on ScrollView or any component that extends from the ScrollView like the FlatList: automaticallyAdjustsScrollIndicatorInsets={automaticallyAdjustsScrollIndicatorInsets}

Picker Removed From Core

cddb97ad18c Remove Picker from OSS (#31772)

Accessibility Support for Entrance/Exit of Lists

25a16123a61 Added Support for Entrance/exit from collection by Flatlist (#31630)

Upgrade Metro to v0.66.1

Commit

Fix Java NullPointerException due to OkHttp

Crash reports were logging the following crashes:

java.lang.NullPointerException: bio == null
       at com.android.org.conscrypt.NativeCrypto.SSL_pending_written_bytes_in_BIO(NativeCrypto.java)
       at com.android.org.conscrypt.NativeSsl$BioWrapper.getPendingWrittenBytes(NativeSsl.java:660)
       at com.android.org.conscrypt.ConscryptEngine.pendingOutboundEncryptedBytes(ConscryptEngine.java:566)
       at com.android.org.conscrypt.ConscryptEngineSocket.drainOutgoingQueue(ConscryptEngineSocket.java:584)
       at com.android.org.conscrypt.ConscryptEngineSocket.close(ConscryptEngineSocket.java:480)
       at okhttp3.internal.Util.closeQuietly(Util.kt:501)
       at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFile:245)
       at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFile:106)
       at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFile:74)
       at okhttp3.internal.connection.RealCall.initExchange$okhttp(ExchangeFile:255)
       at okhttp3.internal.connection.ConnectInterceptor.intercept(ExchangeFile:32)
       ...

This diff upgrades OkHttp from 4.9.0 to 4.9.1 since there is a known concurrency issue happening.

VisionCamera’s Usage of JSI HostObjects

To get a glimpse of the power of JSI, VisionCamera uses it to expose the full Image frame buffer.

Marc

For anyone interested in JSI; VisionCamera uses JSI HostObjects to expose the full Image frame buffer (~10 MB image!) to JS without any copying! You can directly access it’s width/height, format and other props which call into native C++ code.

Tweet

Just look how simple it is to send back a value to JavaScript by returning a jsi::value. See the jsi:: returns of the FrameHostObject::get method


jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
  auto name = propName.utf8(runtime);

  if (name == "toString") {
    auto toString = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
      if (this->frame == nil) {
        return jsi::String::createFromUtf8(runtime, "[closed frame]");
      }
      auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
      auto width = CVPixelBufferGetWidth(imageBuffer);
      auto height = CVPixelBufferGetHeight(imageBuffer);

      NSMutableString* string = [NSMutableString stringWithFormat:@"%lu x %lu Frame", width, height];
      return jsi::String::createFromUtf8(runtime, string.UTF8String);
    };
    return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString);
  }
  if (name == "close") {
    auto close = [this] (jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
      if (this->frame == nil) {
        throw jsi::JSError(runtime, "Trying to close an already closed frame! Did you call frame.close() twice?");
      }
      this->close();
      return jsi::Value::undefined();
    };
    return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "close"), 0, close);
  }

  if (name == "isValid") {
    auto isValid = frame != nil && CMSampleBufferIsValid(frame.buffer);
    return jsi::Value(isValid);
  }
  if (name == "width") {
    this->assertIsFrameStrong(runtime, name);
    auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
    auto width = CVPixelBufferGetWidth(imageBuffer);
    return jsi::Value((double) width);
  }
  if (name == "height") {
    this->assertIsFrameStrong(runtime, name);
    auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
    auto height = CVPixelBufferGetHeight(imageBuffer);
    return jsi::Value((double) height);
  }
  if (name == "bytesPerRow") {
    this->assertIsFrameStrong(runtime, name);
    auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
    auto bytesPerRow = CVPixelBufferGetPlaneCount(imageBuffer);
    return jsi::Value((double) bytesPerRow);
  }
  if (name == "planesCount") {
    this->assertIsFrameStrong(runtime, name);
    auto imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer);
    auto planesCount = CVPixelBufferGetPlaneCount(imageBuffer);
    return jsi::Value((double) planesCount);
  }

  return jsi::Value::undefined();
}

Source

Wix Post - Shared Transitions

Improve continuity and reduce fragmentation for users navigating your #reactnative mobile app with Shared Element Transitions.

How Wix implemented shared transitions.

Cool Game In React Native

I think I already mentioned in previous weeks how friggitydingo's game in React Native is looking awesome: See tweet

How to write a native module with Swift

Akinn Rosa wrote a quick article on how to achieve this.

That Is It!

That’s it for this week. If you want to see more checkout the previous week’s posts here. Subscribe to get notified when new posts are out = )