cmaycumber / expo-keyboard-extension

Expo config plugin that allows creating custom keyboard extensions for iOS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expo Keyboard Extension

npm License Downloads GitHub stars

Create an iOS custom keyboard extension with a custom view using Expo. Supports Apple Sign-In, React Native Firebase (including shared auth session via access groups), custom background, custom height, and custom fonts.

Installation

Install the package

npx expo install expo-keyboard-extension

Update app.json/app.config.js

"expo": {
  ...
  "plugins": ["expo-keyboard-extension"],
  ...
}

Update package.json

{
  ...
  "main": "index.js",
  ...
}

Create an index.js in the root of your project

import { registerRootComponent } from "expo";

import App from "./App";

registerRootComponent(App);

or if you're using expo-router:

import "expo-router/entry";

Create an index.keyboard.js in the root of your project

import { AppRegistry } from "react-native";

// could be any component you want to use as the root component of your keyboard extension's bundle
import KeyboardExtension from "./KeyboardExtension";

// IMPORTANT: the first argument to registerComponent, must be "keyboardExtension"
AppRegistry.registerComponent("keyboardExtension", () => KeyboardExtension);

Update metro.config.js so that it resolves index.keyboard.js as the entry point for the keyboard extension

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");

/**
 * Add support for keyboard.js as a recognized extension to the Metro config.
 * This allows creating an index.keyboard.js entry point for our iOS keyboard extension
 *
 * @param {import('expo/metro-config').MetroConfig} config
 * @returns {import('expo/metro-config').MetroConfig}
 */
function withKeyboardExtension(config) {
  config.transformer.getTransformOptions = () => ({
    resolver: {
      sourceExts: [...config.resolver.sourceExts, "keyboard.js"], // Add 'keyboard.js' as a recognized extension
    },
  });
  return config;
}

module.exports = withKeyboardExtension(getDefaultConfig(__dirname), {
  // [Web-only]: Enables CSS support in Metro.
  isCSSEnabled: true,
});

Need a way to close the keyboard extension? Use the close method from expo-keyboard-extension:

import { close } from "expo-keyboard-extension";
import { Button, Text, View } from "react-native";

export default function KeyboardExtension() {
  return (
    <View style={{ flex: 1 }}>
      <Text>Custom Keyboard</Text>
      <Button title="Close" onPress={close} />
    </View>
  );
}

Options

Exlude Expo Modules

Exclude unneeded expo modules to reduce the keyboard extension's bundle size by adding the following to your app.json/app.config.(j|t)s:

[
  "expo-keyboard-extension",
    {
      "excludedPackages": [
        "expo-dev-client",
        "expo-splash-screen",
        "expo-updates",
        "expo-font",
      ],
    },
],

React Native Firebase

Using React Native Firebase? Given that keyboard extensions are separate iOS targets, they have their own bundle IDs, so we need to create a dedicated GoogleService-Info.plist in the Firebase console, just for the keyboard extension target. The bundle ID of your keyboard extension is your existing bundle ID with .KeyboardExtension as the suffix, e.g. com.example.app.KeyboardExtension.

[
  "expo-keyboard-extension",
    {
      "googleServicesFile": "./path-to-your-separate/GoogleService-Info.plist",
    },
],

You can share a firebase auth session between your main app and the keyboard extension by using the useUserAccessGroup hook. The value for userAccessGroup is your main app's bundle ID with the group. prefix, e.g. group.com.example.app.

Custom Background Color

Want to customize the keyboard extension's background color? Add the following to your app.json/app.config.(j|t)s:

[
  "expo-keyboard-extension",
    {
      "backgroundColor": {
        "red": 255,
        "green": 255,
        "blue": 255,
        "alpha": 0.8 // if 0, the background will be transparent
      },
    },
],

Custom Height

Want to customize the keyboard extension's height? Do this in your app.json/app.config.(j|t)s:

[
  "expo-keyboard-extension",
    {
      "height": 300
    },
],

Custom Fonts

This plugin automatically adds custom fonts to the keyboard extension target if they are embedded in the native project via the expo-font config plugin.

It currently does not support custom fonts that are loaded at runtime, due to an NSURLSesssion error. To fix this, Expo would need to support defining a sharedContainerIdentifier for NSURLSessionConfiguration instances, where the value would be set to the main app's and keyboard extension's app group identifier (e.g. group.com.example.app).

Development

If you want to contribute to this project, you can use the example app to test your changes. Run the following commands to get started:

  1. Start the expo module build in watch mode: npm run build
  2. Start the config plugin build in watch mode: npm run build plugin
  3. cd /example and generate the iOS project: npm run prebuild
  4. Run the app from the /example folder: npm run ios

Troubleshooting

Clear XCode Cache

  1. navigate to ~/Library/Developer/Xcode/DerivedData/
  2. rm -rf folders that are prefixed with your project name

Clear CocoaPods Cache

  1. pod cache clean --all
  2. pod deintegrate

Attach Debugger to Keyboard Extension Process:

  1. In XCode in the top menu, navigate to Debug > Attach to Process.
  2. In the submenu, you should see a list of running processes. Find your keyboard extension's name in this list. If you don't see it, you can try typing its name into the search box at the bottom.
  3. Once you've located your keyboard extension's process, click on it to attach the debugger to that process.
  4. With the debugger attached, you can also set breakpoints within your keyboard extension's code. If these breakpoints are hit, Xcode will pause execution and allow you to inspect variables and step through your code, just like you would with your main app.

Check Device Logs

  1. Open the Console app from the Applications/Utilities folder
  2. Select your device from the Devices list
  3. Filter the log messages by process name matching your keyboard extension target name

Check Crash Logs

  1. On your Mac, open Finder.
  2. Select Go > Go to Folder from the menu bar or press Shift + Cmd + G.
  3. Enter ~/Library/Logs/DiagnosticReports/ and click Go.
  4. Look for any recent crash logs related to your keyboard extension. These logs should have a .crash or .ips extension.

Credits

This project would not be possible without existing work in the react native ecosystem. I'd like to give credit to the following projects and their authors:

About

Expo config plugin that allows creating custom keyboard extensions for iOS

License:MIT License


Languages

Language:TypeScript 67.4%Language:Swift 30.0%Language:Ruby 2.2%Language:JavaScript 0.4%