Building Nota #1 - Restricting React Native Skia Canvas Touch Handler to Pencil touches only

This will be the first part of a series of articles where I write about my journey building Nota.

What's Nota? Forgive the copy: nota allows you to use your Apple Pencil to take notes on your iPad and syncs to Notion - take a glimpse at the header image above, that's nota (at least at the point of this writing)

For building the note-taking aspect for this app, I went with Shopify react-native-skia - an astounding library from the Shopify team. Excited to see where this library takes the react native ecosystem.

I plan on writing an article in the future on how I built the note-taking feature - but that would be a much longer post. For now, I'll be showing how I implemented Apple Pencil only.

The react-native-skia library offers the Canvas component. We can use the onTouch prop and the useTouchHandler hook to track the users' touches on the Canvas component (docs).

The touchHandler tracks all touches, but we want to restrict it to only track touches made by a Pencil.

To get started, we'll edit the node-modules/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaDrawView.mm file.
We want to edit the handleTouches function, we'll be updating the bit that loops through all touches to only consider Pencil touches.

  for (UITouch *touch in touches) {
        if(touch.type == UITouchTypePencil) {
            auto position = [touch preciseLocationInView:self];
            RNSkia::RNSkTouchPoint nextTouch;
            nextTouch.x = position.x;
            nextTouch.y = position.y;
            nextTouch.force = [touch force];
            nextTouch.id = [touch hash];
            auto phase = [touch phase];
            switch(phase) {
              case UITouchPhaseBegan:
                nextTouch.type = RNSkia::RNSkTouchType::Start;
                break;
              case UITouchPhaseMoved:
                nextTouch.type = RNSkia::RNSkTouchType::Active;
                break;
              case UITouchPhaseEnded:
                nextTouch.type = RNSkia::RNSkTouchType::End;
                break;
              case UITouchPhaseCancelled:
                nextTouch.type = RNSkia::RNSkTouchType::Cancelled;
                break;
              default:
                nextTouch.type = RNSkia::RNSkTouchType::Active;
                break;
            }
            
            nextTouches.push_back(nextTouch);
        }
    }

The integral part of the change we're making is updating the code to only handle the touch when the touch.type is UITouchTypePencil.

Next, we'll want to make sure that the changes made to the package remains even after a fresh yarn/npm install. And we'll be using patch-package.

There are a number of articles on doing that. Here's one I used:
https://dev.to/roshangm1/make-changes-to-nodemodule-files-with-patch-package-30h4

And when you have the shopify/react-native-skia package patched, you'll have a patch file similar to this. And re-building the app should allow only Pencil touches on the Canvas.

The roadmap for Nota is public, and I plan on sharing my journey as I build this app.

Comments