Code Monkey home page Code Monkey logo

react-native-colo-loco's Introduction

React Native Colo Loco 🤪

Have you ever needed to write a native iOS and Android module but find yourself deep in Stack Overflow and digging through Xcode and Android Studio?

This library makes it as simple as dropping your Objective-C, Java, Swift, and Kotlin files right next to your JavaScript/TypeScript files.

Colo Loco will find your colocated native files, automatically link them up to the Xcode and Android Studio projects, and you can focus on your code.

Colo Loco in action

iOS simulator showing native alert popup Android emulator showing native alert pop-up

Watch Jamon show how to use React Native Colo Loco!

CleanShot 2023-03-02 at 08 31 33@2x

Installation

Note that Colo Loco doesn't (yet) support Expo.

Add Colo Loco to your development dependencies:

npm install -D react-native-colo-loco
# or
yarn add -D react-native-colo-loco

Once you have installed react-native-colo-loco, you can try running our setup script. This will attempt to automatically patch the necessary files.

npx install-colo-loco

NOTE: It's recommended to run this script with a clean git working tree; if you want to continue without a dirty working tree pass it the --no-git-check flag

Lastly, install pods and run the project to finish installation and compile.

npx pod-install
npm run ios
npm run android

NOTE: If this doesn't work or you have a non-standard project structure, try the manual instructions below.

iOS Manual Installation

Click to expand iOS manual instructions

For iOS, add this to your Podfile (ios/Podfile) (don't forget to change MyApp to your actual app name):

require File.join(File.dirname(`node --print "require.resolve('react-native-colo-loco/package.json')"`), "scripts/ios.rb")
link_colocated_native_files(app_name: 'MyApp', app_path: "../app")

Exclude specific Xcode targets

In some cases you may want to exclude certain targets from being linked. For example, if you have a MyAppTests target, you may not want to link your native files into that target. To do this, the exclude_targets option flag specifies an array of target names to exclude. Just add the following to your Podfile:

link_colocated_native_files(
  app_name: 'MyApp',
  app_path: "../app",
  exclude_targets: ['MyAppTests']
)

You can also specify on an individual file basis which targets you want to link. Add a comment somewhere in the file (recommended near the top) with the following format:

// colo_loco_targets: TestApp, TestAppTests

This will link the file into the TestApp and TestAppTests targets, but not any other targets.

Note that this comment-based approach will take precedence over the exclude_targets option.

Android Manual Installation

Click to expand Android manual instructions

Create a "package" file for your project in ./android/app/src/main/java/com/myapp/MyAppPackage.java (but replace myapp and MyApp with your app's package name and app name).

The contents of this file will be this:

// ./android/app/src/main/java/com/myapp/MyAppPackage.java
package com.myapp; // replace myapp with your app’s package name
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// Replace MyApp with your app's name
public class MyAppPackage implements ReactPackage {
   @Override
   public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
      List<ViewManager> modules = new ArrayList<>();

      // Add all react-native-colo-loco native view managers from ./colocated/ColoLoco.java
      modules.addAll(ColoLoco.colocatedViewManagers(reactContext));

      return modules;
   }

   @Override
   public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
      List<NativeModule> modules = new ArrayList<>();

      // Add all react-native-colo-loco modules from ./colocated/ColoLoco.java
      modules.addAll(ColoLoco.colocatedModules(reactContext));

      return modules;
   }
}

Open up your MainApplication.java file in the same folder and update the following method:

@Override
protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  // Packages that cannot be autolinked yet can be added manually here, for example:
  // packages.add(new MyReactNativePackage());
  packages.add(new MyAppPackage());
  return packages;
}

Open up your ./android/settings.gradle file and add this near the top (replace myapp with your app name):

rootProject.name = 'MyApp'

apply from: new File(["node", "--print", "require.resolve('react-native-colo-loco/package.json')"].execute(null, rootDir).text.trim(), "../scripts/android.groovy")
linkColocatedNativeFiles([
  appName: rootProject.name,
  appPath: "../app",
  appPackageName: "com.myapp",
  androidPath: "./android/app/src/main/java/com/myapp"
])

// rest of file...

Now, when you run yarn android, it'll hardlink your .java files into a colocated folder in your Android project directory and then generate the class ColoLoco which will instantiate & register all of them with your project.

Usage

For native iOS and Android modules and view managers, place your .m, .h, .swift, .java, and .kt files anywhere near your JavaScript/JSX files. They'll be linked in automatically when you run pod install, or in Android's case, when you run npm run android. If the filename ends in *ViewManager, it'll be linked as a view manager.

ios/
android/
app/
  components/
    MyButton.tsx
    MyNativeButtonViewManager.h
    MyNativeButtonViewManager.m
    MyNativeButtonViewManager.java
    MyNativeModule.h
    MyNativeModule.m
    MyNativeModule.java

Examples

iOS Objective-C Example

Let's build a small native module that shows an alert.

In a fresh React Native project, install react-native-colo-loco (see instructions above) and then make a folder called app. Place two files inside of that -- Jamon.h and Jamon.m.

// app/Jamon.h
#import <UIKit/UIKit.h>
#import <React/RCTBridgeModule.h>
@interface Jamon : NSObject <RCTBridgeModule>
@end
// Jamon.m
#import "Jamon.h"

@implementation Jamon

RCT_EXPORT_MODULE();

// Export a method -- `Jamon.hello()`
RCT_EXPORT_METHOD(hello)
{
  // Alerts have to go on the main thread
  dispatch_async(dispatch_get_main_queue(), ^{
    UIAlertView *alert = [[UIAlertView alloc]
      initWithTitle: @"Hello from native!"
      message: @"This is from Jamon.m"
      delegate: self
      cancelButtonTitle: @"Cancel"
      otherButtonTitles: @"Say Hello",
      nil
    ];
    [alert show];
  });
}

@end

Modify the App.js to import the native module:

import { NativeModules } from "react-native"
const { Jamon } = NativeModules

// Now run it:
Jamon.hello()

Run npx pod-install in your terminal and then run your project with yarn ios (or yarn react-native run-ios).

You should see the native alert pop up in your app!

iOS simulator showing native alert popup

Hint: You can read a lot more about iOS native modules here: https://reactnative.dev/docs/native-modules-ios

Android Java example

Create a file called Jamon.java and drop it into your app folder next to your JSX/TSX files.

package com.myapp; // change to your app's package name

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import android.app.AlertDialog;

public class Jamon extends ReactContextBaseJavaModule {
  Jamon(ReactApplicationContext context) {
    super(context);
  }

  @Override
  public String getName() {
    return "Jamon";
  }

  @ReactMethod
  public void hello() {
    // Display a pop-up alert
    AlertDialog.Builder builder = new AlertDialog.Builder(getCurrentActivity());
    builder.setMessage("Hi, everybody!")
      .setTitle("Jamon")
      .setPositiveButton("OK", null);
    AlertDialog dialog = builder.create();
    dialog.show();
  }
}

Now when you import it and run in Android, you'll see the alert pop up!

import { NativeModules } from "react-native"
const { Jamon } = NativeModules

Jamon.hello()

Android emulator showing native alert pop-up

iOS Swift Example

Swift requires a bit more setup, but after that you should be able to drop in .swift files and have them work. Unfortunately, as of now, Swift files still require a .m file to expose them to React Native, so you'll still be making two files.

Note that if you used a recent version of Ignite to create your app, Swift is already set up.

To set up Swift in your project (only has to be done once), click here to expand.

First, open your xcworkspace file (in the ./ios folder) in Xcode.

Click File -> New -> New File in the menu (or hit Cmd+N).

Choose "Swift File" under the Source section. Name it something like EnableSwift and click Create.

Xcode should prompt you with this prompt: Would you like to configure an Objective-C bridging header?

Click Create bridging header (this is key).

Inside that file, add this line:

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#import <React/RCTBridgeModule.h>

Save it, and you now have Swift support. You can close Xcode and let your Mac take a breather.

Now, it's just a matter of adding Swift files to your project. Inside the ./app folder you created in the previous section, add the following Gant.swift file:

// Gant.swift
import Foundation
import UIKit

@objc(Gant)
class Gant : NSObject {
  @objc func hello() {
    // Alerts have to go on the main thread
    DispatchQueue.main.async {
      let alert = UIAlertView(
        title: "Hello from native!",
        message: "This is from Gant.swift",
        delegate: nil,
        cancelButtonTitle: "Cancel",
        otherButtonTitles: "Say Hello"
      )
      alert.show()
    }
  }
}

Also add a Gant.m file next to it to export it to React Native:

// Gant.m
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(Gant, NSObject)
RCT_EXTERN_METHOD(hello)
+ (BOOL)requiresMainQueueSetup { return NO; }
@end

In your App.js, just use it like you did the Jamon native module:

import { NativeModules } from "react-native"
const { Gant } = NativeModules

Gant.hello()

Don't forget to run npx pod-install to link up the new native files.

Then run yarn ios to recompile. You should see the alert pop up! Yay!

Android Kotlin Example

Create a file called Gant.kt in your app folder and drop in these contents:

package com.myapp // change to your package name

import android.app.AlertDialog
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

// change to your app's package name
class Gant internal constructor(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) {
    override fun getName(): String {
        return "Gant"
    }

    @ReactMethod
    fun hello() {
        // Display a pop-up alert
        val builder = AlertDialog.Builder(currentActivity)
        builder.setMessage("Hi, everybody!")
                .setTitle("Gant")
                .setPositiveButton("OK", null)
        val dialog = builder.create()
        dialog.show()
    }
}

In your App.js, just use it like you did the Jamon Java native module:

import { NativeModules } from "react-native"
const { Gant } = NativeModules

Gant.hello()

Native UI Components

Native modules are fun, but even more fun are native UI components.

Native iOS UI Components

To create a native iOS UI component, you can add a ViewManager Objective-C file and header anywhere in your JS folder.

Here's an example that downloads and shows a remote image:

// app/components/MyImageViewManager.h
#import <React/RCTViewManager.h>
#import "UIKit/UIKit.h"
@interface MyImageViewManager : RCTViewManager
@end
// app/components/MyImageViewManager.m
#import "MyImageViewManager.h"

@implementation MyImageViewManager

UIImageView *wrapper;

RCT_EXPORT_MODULE(MyImageViewManager)

- (UIView *)view
{
  wrapper = [[UIImageView alloc] initWithImage:[UIImage new]];
  [self performSelectorInBackground:@selector(loadImageAsync) withObject:nil];
  return wrapper;
}

- (void) loadImageAsync
{
  NSURL *url = [NSURL URLWithString:@"https://logos-world.net/wp-content/uploads/2021/10/Meta-facebook-Logo-700x394.png"];
  // stops the UI until it finishes downloading
  NSData *data = [NSData dataWithContentsOfURL:url];
  UIImage *image = [[UIImage alloc] initWithData:data];
  dispatch_async(dispatch_get_main_queue(), ^{
    wrapper.image = image;
  });
}

@end

To use this in your JSX, use requireNativeComponent like so:

import { requireNativeComponent } from "react-native"
const MyImageView = requireNativeComponent("MyImageView")

function MyComponent() {
  return <MyImageView style={{ width: 200, height: 100 }} />
}

Native Android UI Components

To create a native Android UI component, you can add a java file anywhere in your JS folder structure, but make sure the class name ends in *ViewManager.

Here's an example that downloads and shows a remote image:

// app/components/MyImageViewManager.java
package com.myapp; // change to your app's package name

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.views.image.ReactImageView;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.Log;
import android.view.View;

import java.net.URL;

public class MyImageViewManager extends SimpleViewManager<ReactImageView> {
  // This is the string we use to identify this view when we call
  // requireNativeComponent("MyImageView") in JS.
  public static final String REACT_CLASS = "MyImageView";

  // We hang onto a reference of our React app context for later use.
  ReactApplicationContext mCallerContext;
  ReactImageView mView;

  // This is the URL of the image we'll show
  private final String logoURL = "https://logos-world.net/wp-content/uploads/2021/10/Meta-facebook-Logo-700x394.png";

  // Constructor -- saves a reference to the React context
  public MyImageViewManager(ReactApplicationContext reactContext) {
    mCallerContext = reactContext;
  }

  // Required method to allow React Native to know what the name of this class is.
  @Override
  public String getName() {
    return REACT_CLASS;
  }

  // This method is where we create our native view.
  @Override
  protected ReactImageView createViewInstance(ThemedReactContext reactContext) {
    // Instantiate a new ReactImageView
    // Fresco is a Facebook library for managing Android images and the memory they use.
    // https://github.com/facebook/fresco
    mView = new ReactImageView(reactContext, Fresco.newDraweeControllerBuilder(), null, mCallerContext);

    // This "handler" allows the `startDownloading` thread to call back to *this* thread.
    // Otherwise crashy crashy!
    final Handler mainThread = new Handler();

    // We'll download the image now and apply it back to this view
    startDownloading(mainThread);

    // Return our view back to React Native.
    return mView;
  }

  // Download our image.
  private void startDownloading(final Handler mainThread) {
    // Create a new background thread to download our image
    new Thread(() -> {
      try {
        // Download, blocking THIS background thread but not the main one
        URL url = new URL(logoURL);
        final Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());

        // Go back to the main thread and set the image bitmap
        mainThread.post(() -> mView.setImageBitmap(bmp));
      } catch (Exception e) {
        Log.e("ReactImageManager", "Error : " + e.getMessage());
      }
    }).start();
  }
}

To use this in your JSX, use requireNativeComponent like so:

import { requireNativeComponent } from "react-native"
const MyImageView = requireNativeComponent("MyImageView")

function MyComponent() {
  return <MyImageView style={{ width: 200, height: 100 }} />
}

Kotlin Example

If your project is Kotlin-ready, you can drop in a Kotlin view manager and use it like so:

package com.myapp

import android.widget.TextView
import android.graphics.Color
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.bridge.ReactApplicationContext

class WelcomeViewManager (reactAppContext: ReactApplicationContext) : SimpleViewManager<TextView>() {
  override fun getName(): String {
    return "WelcomeView"
  }

  override fun createViewInstance(reactContext: ThemedReactContext): TextView {
    val welcomeTextView: TextView = TextView(reactContext)
    welcomeTextView.text = "WELCOME!"
    return welcomeTextView
  }

  @ReactProp(name = "text")
  fun setTextFromProp(view: TextView, myText: String) {
    view.text = "${myText.uppercase()}!"
  }

  @ReactProp(name = "textColor")
  fun setTextColorFromProp(view: TextView, myTextColor: String) {
    // set text color
    view.setTextColor(Color.parseColor(myTextColor))
  }
}

Then, in your JSX/TSX:

const WelcomeView = requireNativeComponent("WelcomeView")

function MyWelcomeView() {
  return <WelcomeView text="Welcome!" textColor="#FFFFFF" style={{ width: 200, height: 100 }} />
}

You should see the text show up in your app!

License

This package is licensed under the MIT license.

Limitations/Assumptions

Android assumptions

On Android, our assumption is that your native files live in your app's main package (com.yourpackage). If you need them to live in their own package, you may not be able to colocate those files.

We've considered adding some magic comments to allow for more fine-grained control over package imports and instantiation. For example, something like this (it's not implemented yet so don't try it):

// @import-template import com.myotherpackage
// @instantiation-template new MyModule(null, "Hello", false)
// @instantiate false

However, these are edge-cases, and likely best if you create your own package / imports in the ./android/src/... folder yourself.

Troubleshooting

  1. On iOS, make sure you've run npx pod-install to link any new / changed native modules before building your app
  2. If you're getting obscure native errors, try opening the project in Android Studio or Xcode and building from there to get more targeted errors
  3. If you think the issue is with React Native Colo Loco, try creating a brand-new app using the instructions earlier in the README and replicate the problem there. Then file an issue with a link to the replication repo. Issues without replication steps or repos will most likely be closed without resolution because who's got time for that?

If you continue having problems, join the Infinite Red Slack community at https://community.infinite.red and ask in the #react-native channel. Make sure to mention you are using React Native Colo Loco.

If you need help from pros, consider hiring Infinite Red, my React Native consulting company.

react-native-colo-loco's People

Contributors

a7medev avatar jamonholmgren avatar morganick avatar semantic-release-bot avatar ste7en avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-colo-loco's Issues

Can't locate source folder on Android

I created a new app using npx react-native init MyApp then installed and set up colo-loco using yarn install-colo-loco
The iOS version works well, while the Android one doesn't.
Whenever I run yarn android I get this error:

Error: Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081

FAILURE: Build failed with an exception.

  • Where:
    Script '/private/tmp/ColoLocoTest/node_modules/react-native-colo-loco/scripts/android.groovy' line: 10

  • What went wrong:
    A problem occurred evaluating settings 'android'.

/Users/a7medev/.gradle/daemon/app does not exist.

The problem I guess is that it's looking for the "app" folder (Source folder I picked in the install script) in the .gradle/daemon folder (I changed "app" to "src" and got an error with .../.gradle/daemon/src does not exist.

Sweep: Add YouTube link to README

Add a link to the new YouTube video I made about react-native-colo-loco.

Description of the YouTube video:

"WELCOME FRIENDS!! Today I'm hacking Xcode workspace files with a script I wrote a couple years ago, react-native-colo-loco!

We're adding a new feature requested by one of my project teams at Infinite Red (https://infinite.red) AND doing test-driven development ... the easy way (with ChatGPT and Github Copilot).

Please like the video & subscribe to the channel! And let me know on Twitter what you think. And if you missed my last video about my adventure trying to upgrade an open source project, check it out here:

• NEW CODING SERIES...

  • Jamon

Pull request: https://github.com/jamonholmgren/reac...

Twitter: @jamonholmgren
My website: https://jamon.dev
My company website: https://infinite.red

0:00 Welcome, Friends!
1:25 Intro to our quest
2:12 Creating an iOS share extension
2:45 Installing react-native-colo-loco
5:07 Customizing native code
7:28 Adding tests (test-driven-development!)
10:08 Adding the feature
11:50 Testing manually
12:54 Updating docs
13:13 Creating pull request
13:35 Goodbye!"

Make the addition flow well with the existing README contents.

Project.pbxproj files hash changes at every pod install

Each time I run the react-native-colo-loco's link_colocated_native_files Podfile script it relinks files to my Xcode project resulting in a new entry in PBXBuildFile section of the project. This makes the project file to be tracked as changed by Git even if the native module did not change or a new one is linked.

Sweep: Add YouTube link to README

Add a link to the new YouTube video I made about react-native-colo-loco.

Description of the YouTube video for context:

"WELCOME FRIENDS!! Today I'm hacking Xcode workspace files with a script I wrote a couple years ago, react-native-colo-loco!

We're adding a new feature requested by one of my project teams at Infinite Red (https://infinite.red) AND doing test-driven development ... the easy way (with ChatGPT and Github Copilot).

Please like the video & subscribe to the channel! And let me know on Twitter what you think. And if you missed my last video about my adventure trying to upgrade an open source project, check it out here:

• NEW CODING SERIES...

Jamon
Pull request: https://github.com/jamonholmgren/reac...

Twitter: @jamonholmgren
My website: https://jamon.dev
My company website: https://infinite.red

0:00 Welcome, Friends!
1:25 Intro to our quest
2:12 Creating an iOS share extension
2:45 Installing react-native-colo-loco
5:07 Customizing native code
7:28 Adding tests (test-driven-development!)
10:08 Adding the feature
11:50 Testing manually
12:54 Updating docs
13:13 Creating pull request
13:35 Goodbye!"

Make the addition flow well with the existing README contents.

Add a new section that is called "Contributing to React Native Colo Loco". This video should be referenced in that section, with a description (it's a demo of contributing, not a tutorial).

The automated release is failing 🚨

🚨 The automated release from the main branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the main branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two Factor Authentication for your account, set its level to "Authorization only" in your account settings. semantic-release cannot publish with the default "
Authorization and writes" level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Sweep: extract functionality into new ruby method

In the ios.rb script, the functionality under this comment:

# Remove files from the existing colocated file_group that are not present in the colocated_files array

...extract that to its own function to be more modular.

Feature: allow for specifying targets per-file

react-native-colo-loco allows you to exclude iOS targets across the board, but it would be really nice to specify which targets a native file applies to on a file-by-file basis.

My current idea is to add a comment to the file, something like this:

// colo_loco_targets: PizzaApp, PizzaAppTest, PizzaAppWidget

Could even have an exclude there as well, if preferred:

// colo_loco_exclude_targets: PizzaAppTest

If anyone has an opinion here, by all means let me know!

Colocated files hash changes after #16

There is a bug in PR #16 that tests did not raise. I explained it here.

To solve it we should always check for file realpaths:

colocated_files.map(&:real_path).include?(file.real_path)

[Android] Ignited app with colo loco breaks when building on AppCenter

I built a new app with Ignite (love it!), and it builds fine locally.

When I build in Android Studio it works fine. When I build it on AppCenter, it fails and points to Colo Loco:

* Where:
Script '/Users/runner/work/1/s/ThriveBusiness/node_modules/react-native-colo-loco/scripts/android.groovy' line: 17

* What went wrong:
A problem occurred evaluating settings 'android'.
> /Users/runner/work/1/app does not exist.

The only non-standard part of my Ignite setup is that I use /src instead of /app for my JS folder. I've tried both of these in settings.gradle

apply from: '../node_modules/react-native-colo-loco/scripts/android.groovy'
linkColocatedNativeFiles([
  appPath: "../app", // also tried using "../src"
  appPackageName: "com.myappname",
  androidPath: "./android/app/src/main/java/com/myappname"
])

I can see that whatever I change this appPath to is what comes out in the AppCenter build error as not existing, e.g. if I make it ../app it will say > /Users/runner/work/1/app does not exist., and if I do ../src it will say > /Users/runner/work/1/src does not exist.

May be a clue. Either way, I've opted to remove colo loco from my project for now.

android.groovy determines root project path from user.dir property

When running a gradle task from Fastlane, if the Fastfile is defined project-wide and not in the Android / iOS respective folders, gradle fails because the relative appPath I'm providing to linkColocatedNativeFiles is relative to the system property user.dir as in lines 17-18.

Unfortunately neither the rootDir Gradle property can be used as it would be appended to System.getProperty('user.dir') path.

Add support for MainApplication.kt

How to reproduce:

  1. npx ignite-cli@latest new
  2. npx install-colo-loco

Gets the following error:

npx install-colo-loco
Setting up React Native Colo Loco!
App name? [AdvancedContacts]
Source folder? [app]
App package name? [com.advancedcontacts]
Setting up React Native Colo Loco for AdvancedContacts in app
node:internal/readline/emitKeypressEvents:74
            throw err;
            ^

Error: ENOENT: no such file or directory, open './android/app/src/main/java/com/advancedcontacts/MainApplication.java'
    at Object.openSync (node:fs:599:3)
    at Object.readFileSync (node:fs:467:35)
    at setupAndroid (/Users/joshuayoes/Code/AdvancedContacts/node_modules/react-native-colo-loco/scripts/install-colo-loco:216:38)
    at Interface.setupColoLoco (/Users/joshuayoes/Code/AdvancedContacts/node_modules/react-native-colo-loco/scripts/install-colo-loco:95:3)
    at Interface.emit (node:events:525:35)
    at Interface.close (node:internal/readline/interface:536:10)
    at /Users/joshuayoes/Code/AdvancedContacts/node_modules/react-native-colo-loco/scripts/install-colo-loco:80:14
    at [_onLine] [as _onLine] (node:internal/readline/interface:423:7)
    at [_line] [as _line] (node:internal/readline/interface:886:18)
    at [_ttyWrite] [as _ttyWrite] (node:internal/readline/interface:1264:22) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: './android/app/src/main/java/com/advancedcontacts/MainApplication.java'
}

Node.js v18.7.0

Expo 50 now creates android/app/src/main/java/com/advancedcontacts/MainApplication.kt instead of android/app/src/main/java/com/advancedcontacts/MainApplication.java.

We need to add support for detecting if there is a .java or .kt entrypoint here https://github.com/jamonholmgren/react-native-colo-loco/blob/main/scripts/install-colo-loco#L215

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.