Skip to content

Commit

Permalink
4.2.0 (#83)
Browse files Browse the repository at this point in the history
* Add Survicate plugin for Expo integration

* React Native 4.2.0

* Fix newline issue in SurvicatePluginProps definition

* Readme Expo installation instructions refactor
  • Loading branch information
SurvicatePawelGodlewski committed Mar 19, 2024
1 parent 611889d commit ccf6412
Show file tree
Hide file tree
Showing 11 changed files with 2,512 additions and 59 deletions.
56 changes: 51 additions & 5 deletions README.md
@@ -1,17 +1,34 @@
# @survicate/react-native-survicate [![npm version](https://badge.fury.io/js/%40survicate%2Freact-native-survicate.svg)](https://badge.fury.io/js/%40survicate%2Freact-native-survicate)
# @survicate/react-native-survicate ![npm version](https://img.shields.io/npm/v/%40survicate%2Freact-native-survicate)

Integrate Survicate into your React Native application to collect user feedback seamlessly.

## Requirements:
- iOS at least on version 12.0
- Android at least on version 5
- React Native at least on version 0.60.0

## Getting started
## Installation
This package can be installed using npm or yarn. If you're using Expo, follow the Expo-specific instructions.

### Using npm
```sh
npm install @survicate/react-native-survicate --save
```

### Using yarn
```sh
yarn add @survicate/react-native-survicate
```

`$ npm install @survicate/react-native-survicate --save`
### Using expo
> Please note that due to custom native code in this package "Expo Go" is not available.
### Mostly automatic installation
To use @survicate/react-native-survicate in an Expo managed project use npm, yarn or expo-cli.
```sh
expo install @survicate/react-native-survicate
```

`$ react-native link @survicate/react-native-survicate`
## Configuration

### Configuring Survicate Bindings for iOS
- Add your Survicate workspace key to `Info.plist`
Expand Down Expand Up @@ -45,6 +62,25 @@ allprojects {
</application>
```

### Configuring Survicate Bindings for Expo
- Add [config plugin](https://docs.expo.dev/config-plugins/introduction/) to `plugins` array of your `app.json` or `app.config.js`
```json
{
"expo": {
"plugins": [
[
"@survicate/react-native-survicate",
{
"workspaceKey": "YOUR_WORKSPACE_KEY"
}
]
]
}
}
```
> Please note that every time you change the props or plugins, you'll need to [rebuild](https://docs.expo.dev/workflow/customizing/) the native app.

## Usage
```javascript
import Survicate, {UserTrait} from '@survicate/react-native-survicate';
Expand All @@ -70,6 +106,16 @@ const subscription = Survicate.addSurvicateEventListener(listener);
Survicate.reset();
```

## Issues

Got an Issue?

To make things more streamlined, we’ve transitioned our issue reporting to our customer support platform. If you encounter any bugs or have feedback, please reach out to our customer support team. Your insights are invaluable to us, and we’re here to help ensure your experience is top-notch!

Contact us via Intercom in the application, or drop us an email at: [hello@survicate.com]

Thank you for your support and understanding!

## Changelog

The Survicate Mobile SDK change log can be found [here](https://developers.survicate.com/mobile-sdk/react-native/#changelog)
2 changes: 1 addition & 1 deletion android/build.gradle
Expand Up @@ -120,7 +120,7 @@ repositories {
dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation ('com.survicate:survicate-sdk:4.1.1')
implementation ('com.survicate:survicate-sdk:4.2.0')
}

if (isNewArchitectureEnabled()) {
Expand Down
10 changes: 10 additions & 0 deletions app.plugin.js
@@ -0,0 +1,10 @@
const packageJson = require('./package.json');

const pkg = {
name: packageJson.name,
version: packageJson.version,
};

const plugin = require('./lib/commonjs/expo/withSurvicate');

module.exports = plugin.default(pkg);
29 changes: 22 additions & 7 deletions package.json
@@ -1,7 +1,7 @@
{
"name": "@survicate/react-native-survicate",
"title": "React Native Survicate Bindings",
"version": "4.1.1",
"version": "4.2.0",
"description": "React Native bindings for Survicate Mobile SDK",
"main": "lib/commonjs/index.js",
"module": "lib/module/index.js",
Expand All @@ -13,12 +13,19 @@
"lib",
"android",
"ios",
"cpp",
"app.plugin.js",
"react-native-survicate.podspec",
"!android/build",
"!ios/build",
"!android/gradle",
"!android/gradlew",
"!android/gradlew.bat",
"!android/local.properties",
"!**/__tests__",
"!**/__fixtures__",
"!**/__mocks__"
"!**/__mocks__",
"!**/.*"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
Expand All @@ -31,24 +38,32 @@
"baseUrl": "https://github.com/Survicate/survicate-react-native-sdk"
},
"keywords": [
"react-native"
"react-native",
"expo"
],
"author": {
"name": "Survicate",
"email": "help@survicate.com"
},
"author": "Survicate <hello@survicate.com> (https://survicate.com/)",
"license": "MIT",
"licenseFilename": "LICENSE",
"readmeFilename": "README.md",
"bugs": {
"url": "https://survicate.com"
},
"peerDependencies": {
"expo": ">=49",
"react": ">=16.8.6",
"react-native": ">=0.60.0"
},
"peerDependenciesMeta": {
"expo": {
"optional": true
}
},
"devDependencies": {
"@tsconfig/react-native": "^3.0.2",
"@types/jest": "^29.5.4",
"@types/react": "^18.2.21",
"@types/react-test-renderer": "^18.0.1",
"expo": "^50.0.11",
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-builder-bob": "^0.23.1",
Expand Down
2 changes: 1 addition & 1 deletion react-native-survicate.podspec
Expand Up @@ -21,7 +21,7 @@ Pod::Spec.new do |s|
s.requires_arc = true

s.dependency "React"
s.dependency "Survicate", "4.1.1"
s.dependency "Survicate", "4.2.0"
# ...
# s.dependency "..."

Expand Down
3 changes: 3 additions & 0 deletions src/expo/types.ts
@@ -0,0 +1,3 @@
export type SurvicatePluginProps = {
workspaceKey: string
}
20 changes: 20 additions & 0 deletions src/expo/withSurvicate.ts
@@ -0,0 +1,20 @@
import { ConfigPlugin, createRunOncePlugin } from "@expo/config-plugins";
import { SurvicatePluginProps } from "./types";
import { withSurvicateAndroidManifest, withSurvicateAndroidMavenRepository } from "./withSurvicateAndroid";
import { withSurvicateIosInfoPlist } from "./withSurvicateiOS";

const withSurvicateReactNative: ConfigPlugin<SurvicatePluginProps> = (
config,
props
) => {
let newConfig = config;
newConfig = withSurvicateAndroidManifest(newConfig, props);
newConfig = withSurvicateAndroidMavenRepository(newConfig);
newConfig = withSurvicateIosInfoPlist(newConfig, props);
return newConfig;
};

const configPlugin = (pkg: { name: string; version: string }) =>
createRunOncePlugin(withSurvicateReactNative, pkg.name, pkg.version);

export default configPlugin;
100 changes: 100 additions & 0 deletions src/expo/withSurvicateAndroid.ts
@@ -0,0 +1,100 @@
import {
AndroidConfig,
ConfigPlugin,
withAndroidManifest,
withProjectBuildGradle,
} from "expo/config-plugins";
import { ExpoConfig } from "expo/config";
import { SurvicatePluginProps } from "./types";
import {
MergeResults,
createGeneratedHeaderComment,
removeGeneratedContents,
} from "@expo/config-plugins/build/utils/generateCode";

// Using helpers keeps error messages unified and helps cut down on XML format changes.
const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } =
AndroidConfig.Manifest;

export const withSurvicateAndroidManifest: ConfigPlugin<
SurvicatePluginProps
> = (config: ExpoConfig, props: SurvicatePluginProps) => {
return withAndroidManifest(config, async (config) => {
// Modifiers can be async, but try to keep them fast.
config.modResults = await setCustomConfigAsync(
config.modResults,
props.workspaceKey
);
return config;
});
};

async function setCustomConfigAsync(
androidManifest: AndroidConfig.Manifest.AndroidManifest,
workspaceKey: string
): Promise<AndroidConfig.Manifest.AndroidManifest> {
// Get the <application /> tag and assert if it doesn't exist.
const mainApplication = getMainApplicationOrThrow(androidManifest);

addMetaDataItemToMainApplication(
mainApplication,
// value for `android:name`
"com.survicate.surveys.workspaceKey",
// value for `android:value`
workspaceKey
);

return androidManifest;
}

export const withSurvicateAndroidMavenRepository: ConfigPlugin = (config) => {
return withProjectBuildGradle(config, async (config) => {
if (config.modResults.language !== "groovy") {
console.warn(
"Unsupported language for build.gradle. Only 'groovy' is supported."
);
return config;
}

config.modResults.contents = await appendContents({
src: config.modResults.contents,
newSrc: `allprojects { repositories { maven { url 'https://repo.survicate.com' } } }`,
tag: "@survicate/react-native-survicate",
comment: "//",
}).contents;
return config;
});
};

// Fork of config-plugins mergeContents, but appends the contents to the end of the file.
function appendContents({
src,
newSrc,
tag,
comment,
}: {
src: string;
newSrc: string;
tag: string;
comment: string;
}): MergeResults {
const header = createGeneratedHeaderComment(newSrc, tag, comment);
if (!src.includes(header)) {
// Ensure the old generated contents are removed.
const sanitizedTarget = removeGeneratedContents(src, tag);
const contentsToAdd = [
// @something
header,
// contents
newSrc,
// @end
`${comment} @generated end ${tag}`,
].join("\n");
return {
contents: sanitizedTarget ?? src + contentsToAdd,
didMerge: true,
didClear: !!sanitizedTarget,
};
}
return { contents: src, didClear: false, didMerge: false };
}
11 changes: 11 additions & 0 deletions src/expo/withSurvicateiOS.ts
@@ -0,0 +1,11 @@
import { ConfigPlugin, withInfoPlist } from 'expo/config-plugins';
import {SurvicatePluginProps} from './types';

export const withSurvicateIosInfoPlist: ConfigPlugin<SurvicatePluginProps> = (config, props: SurvicatePluginProps) => {
return withInfoPlist(config, (config) => {
config.modResults.Survicate = {
WorkspaceKey: props.workspaceKey,
};
return config;
});
};
2 changes: 1 addition & 1 deletion tsconfig.json
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@amplitude/react-native": ["./src/index"]
"@survicate/react-native-survicate": ["./src/index"]
},
"allowUnreachableCode": false,
"allowUnusedLabels": false,
Expand Down

0 comments on commit ccf6412

Please sign in to comment.