Using git patch or how to live with your packages not updating

There’s a longstanding bug in react-native that has been active since 2018. Korean text is broken on iOS (especially if you move the input cursor to the beginning of the line)

https://github.com/facebook/react-native/issues/19339

Various fixes were merged and reverted over the years (they cause problems in some other places)

Recently (2022 – 4 years later), a better fix were merged into react-native’s main branch

https://github.com/facebook/react-native/pull/32523

However it’s still unclear when this will get released, and it will take even more time for us to upgrade react-native

In order to use this in our final product, we’ll need to patch react-native manually

  1. Download react-native normally via npm install
  2. Patch node_modules/react-native/Libraries/Text/TextInput/RCTBaseTexinputView.m
  3. Build the project

Generating the patch

Let’s download the react-native repository

git clone https://github.com/facebook/react-native.git

You’ll find that it take a veeery long time

Let’s just get the last 1,000 commits instead

git clone --depth 1000 https://github.com/facebook/react-native.git

Much faster!

Next, reset the branch to the commit we want to extract (You can get the commit ID from the pull request, look at the end)

git reset --hard 1a83dc36ce0af33ac7a3c311354fce4bfa5ba1a3

Next, generate the patch file

git format-patch -1 main Libraries/Text/TextInput/RCTBaseTextInputView.m

Explanation

  • git format-patch: generate patch file
  • -1: from last 1 commit
  • main: from main branch
  • Libraries/Text/TextInput/RCTBaseTextInputView.m: patch to the file, omit to generate patch for the whole commit

Applying the patch

A cursory search on the internet will give you some npm package that you should install to apply a patch file. However, most *nix environment have a tool called patch already installed. We can utilize this

Let’s add some script to `package.json`:

    "patch-3882": "patch -st -p1 -d node_modules/react-native < patches/3882-fix-reactnative-textinput.patch",
    "pod": "pod-install",
    "postinstall": "npm run patch-3882; npm run pod",
    "postuninstall": "npm run patch-3882; npm run pod",

Explanation

  • postinstall / postuninstall will run after each package installation with npm. This will ensure our version of react-native stays patched. Also this will work on your existing build pipelines
  • patch-3882: name of your custom build action
  • patch: the patch command
  • -st: run silently, ignore errors, assume the best
  • -p1: convert git’s format to patch format by truncating the first level of directory from the patch file
  • -d: specify the working directory, in this case, react-native’s
  • < patchfile: pipe the patchfile into the patch command, this is not an input parameter

Gotchas:

  • don’t use “&&” to combine commands, use “;” if you are using Microsoft AppCenter to build your binaries. “&&” will give an “unexpected end of file” error due to the shell on the build agent

TIL (react native, EC2, gvm)

react-native

Launching two instances of a react-native project in two simulators

You’ll see this error when you try to run the second instance

error Failed to launch the app on simulator, An error was encountered processing the command (domain=com.apple.CoreSimulator.SimError, code=405):
Unable to lookup in current state: Shutdown

This is because react-native runner won’t start the second emulator instance automatically. You need to start it by opening xcode -> window -> devices & simulators -> simulators -> start the desired simulator.

Then you can run npx react-native run-ios --simulator="iPhone XXX" again

Or you can just run the program in XCode and select the second simulator.

When cannot connect to EC2 instance with external IP

  • Check the subnet’s routing table
  • There should be an igw-something route. If not, won’t be able to connect to the instance from the internet
  • Select a different subnet if such a function is desired
  • Don’t need to allocate an Elastic IP address

gvm install go1.14

  • Will install go 1.14.0 (not the latest version of go)
  • Must specify specific version of go to install latest (which is different from nvm)

Run Flutter app on iOS 2021 edition

You need an apple developer account and XCode

Open the Flutter app in XCode

In Android Studio, go to Tools / Flutter / Open iOS module in XCode. I know, using ANDROID studio to make apps for an iPhone…

Prepare XCode

Connect your phone to the computer. On the top left part, click Runner > and select your phone. If you don’t see your device you’ll need to troubleshoot, don’t select “Any iOS device”

Go to XCode / Preferences / Account tab, press the plus button, select Apple ID and login to your Developer account. You’ll be prompted for keychain access, allow all. After you are done, make sure a team is available. Some tutorials made you do this step by manually creating a CSR key on your computer and upload it to Apple, following the wizard in XCode is much easier

Next, select runner on the left pane, and select signing & capabilities, make sure automatically manage signing is selected

Remotely debug your app

  • In XCode, select Windows / Device and simulators
  • Click on your phone, check the connect via network button

Wait until there’s a globe next to your phone’s name. That’s it, you can now disconnect your phone from the computer and deploy your app remotely to your phone by clicking the Run button

The run button

Automatically allow go binary in goland to listen on MacOS

Everytime you compile a go binary in goland and start it, MacOS will ask you to allow the binary to listen for incoming connection, which can quickly become a nuisance. To always allow the binary, do two things

Listen only on “localhost”

Set the execution environment to HOST=”localhost” for gin

Code sign the executable before launch

VoilĂ ! No more prompts!