Compare commits

..
Author SHA1 Message Date
evanbacon e57c2a75a2 Update app.json 2022-05-27 11:54:42 -05:00
evanbacon 92776140fe wip 2022-05-27 11:53:49 -05:00
481 changed files with 31979 additions and 14382 deletions

No files matched your search

+7 -3
View File
@@ -29,15 +29,19 @@ body:
attributes:
label: Config Plugin
options:
- '@config-plugins/apple-settings'
- '@config-plugins/android-jsc-intl'
- '@config-plugins/detox'
- '@config-plugins/ffmpeg-kit-react-native'
- '@config-plugins/ios-stickers'
- '@config-plugins/react-native-adjust'
- '@config-plugins/react-native-ble-plx'
- '@config-plugins/react-native-blob-util'
- '@config-plugins/react-native-branch'
- '@config-plugins/react-native-callkeep'
- '@config-plugins/react-native-dynamic-app-icon'
- '@config-plugins/react-native-google-cast'
- '@config-plugins/react-native-pdf'
- '@config-plugins/react-native-siri-shortcut'
- '@config-plugins/react-native-quick-actions'
- '@config-plugins/react-native-webrtc'
validations:
required: true
@@ -59,7 +63,7 @@ body:
label: Reproducible demo
description: >-
This should include as little code as possible, do not simply link your
entire project. If a reproducible demo is not provided, it is very
entire project. If a reproducible demo is not provided, it is very
likely your issue will be closed. Read [here more
guidance](https://stackoverflow.com/help/mcve).
validations:
+16 -7
View File
@@ -6,30 +6,39 @@ contact_links:
If you have a question about an Expo Config Plugin, please ask it on the
forums, discord, Twitter, or Stack Overflow.
url: https://forums.expo.io/
- about: E2E tests and automation for mobile
name: 📦 detox issues
url: https://github.com/wix/Detox/issues
- about: FFmpeg Kit for React Native
name: 📦 ffmpeg-kit-react-native issues
url: https://github.com/tanersener/ffmpeg-kit/issues
- about: Adjust React Native SDK
name: 📦 react-native-adjust issues
url: https://github.com/adjust/react_native_sdk/issues
- about: React Native Bluetooth Low Energy library
name: 📦 react-native-ble-plx issues
url: https://github.com/Polidea/react-native-ble-plx/issues
- about: >-
A module provides upload, download, and files access API. Supports file
stream read/write for process large files.
name: 📦 react-native-blob-util issues
url: https://github.com/RonRadtke/react-native-blob-util/issues
- about: Branch Metrics React Native SDK
name: 📦 react-native-branch issues
url: >-
https://github.com/BranchMetrics/react-native-branch-deep-linking-attribution/issues
- about: iOS 10 CallKit and Android ConnectionService Framework For React Native
name: 📦 react-native-callkeep issues
url: https://github.com/react-native-webrtc/react-native-callkeep/issues
- about: Programmatically change the app icon in React Native.
name: 📦 react-native-dynamic-app-icon issues
url: https://github.com/idearockers/react-native-dynamic-app-icon/issues
- about: React Native wrapper for the Google Cast SDK for iOS and Android
name: 📦 react-native-google-cast issues
url: >-
https://github.com/react-native-google-cast/react-native-google-cast/issues
- about: A react native PDF view component, support ios and android platform
name: 📦 react-native-pdf issues
url: https://github.com/wonday/react-native-pdf/issues
- about: A React Native library that enables you to use iOS 12+ Siri Shortcuts.
name: 📦 react-native-siri-shortcut issues
url: https://github.com/Gustash/react-native-siri-shortcut/issues
- about: A react-native interface for Touch 3D home screen quick actions
name: 📦 react-native-quick-actions issues
url: https://github.com/jordanbyron/react-native-quick-actions/issues
- about: WebRTC for React Native
name: 📦 react-native-webrtc issues
url: https://github.com/react-native-webrtc/react-native-webrtc/issues
+2 -2
View File
@@ -1,5 +1,5 @@
name: '⭐️ Config Plugin Request'
description: 'Suggest an idea for a new Expo Config Plugin.'
name: "⭐️ Config Plugin Request"
description: "Suggest an idea for a new Expo Config Plugin."
labels: enhancement
body:
- type: markdown
+1 -1
View File
@@ -2,7 +2,7 @@
🚨 We use semantic release (a bot publishes everything automatically)
🚨 so please use conventional commit style for the PR title:
🚨 https://www.conventionalcommits.org/en/v1.0.0/
🚨 Example: feat(ios-stickers): add new step
🚨 Example: feat(detox): add new step
-->
# Why
+91
View File
@@ -0,0 +1,91 @@
# AUTO GENERATED:
# This file was generated by running the following in the root directory:
#
# yarn update-dependabot-config
version: 2
updates:
- package-ecosystem: npm
directory: packages/android-jsc-intl
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/detox
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/ffmpeg-kit-react-native
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/ios-stickers
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-adjust
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-ble-plx
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-blob-util
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-branch
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-callkeep
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-dynamic-app-icon
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-google-cast
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-pdf
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-quick-actions
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
- package-ecosystem: npm
directory: packages/react-native-webrtc
schedule:
interval: daily
time: '09:00'
timezone: America/Los_Angeles
+5 -23
View File
@@ -5,34 +5,16 @@ on:
branches: [main]
paths:
- .github/workflows/lint-md.yml
- '**.md'
- "**.md"
pull_request:
paths:
- .github/workflows/lint-md.yml
- '**.md'
- "**.md"
jobs:
lint-md:
runs-on: ubuntu-latest
steps:
- name: 👀 Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
- name: 🔨 Install pnpm
uses: pnpm/setup@703c52620218391530e48b9e8870d5c0082e1b9b # v2.1.0
with:
install: false
- name: 🔨 Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: pnpm
- name: Install packages
run: pnpm install --frozen-lockfile
- name: Check Markdown links
run: pnpm exec remark --use validate-links . .github
- uses: actions/checkout@v2
- run: npm install
- run: npx remark --use validate-links . .github
+37
View File
@@ -0,0 +1,37 @@
name: Release
# https://github.com/bent10/monorepo-starter/blob/main/docs/recipes/release-automation.md
on:
push:
branches:
- main
jobs:
release:
name: Releasing
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: yarn install --frozen-lockfile --check-files
- run: yarn lerna run prepare --stream
# If the dry run fails then it will prevent us from automatically breaking the repo.
- name: Semantic release (dry run)
run: npx multi-semantic-release --dry-run --ignore-private-packages
env:
GITHUB_TOKEN: ${{ github.token }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Semantic release
# use `--ignore-packages` to ignore packages on bumping process
# npx multi-semantic-release --ignore-packages=packages/a/**,packages/b/**
run: npx multi-semantic-release --ignore-private-packages
env:
GITHUB_TOKEN: ${{ github.token }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+48 -30
View File
@@ -2,47 +2,65 @@ name: Test Packages
on:
push:
branches: [main]
pull_request: {}
pull_request:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node: ["16", "17"]
name: Build with Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Setup node
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- run: yarn install --frozen-lockfile --check-files
- run: yarn lerna run prepare --stream
- uses: actions/cache@v2
with:
path: "*"
key: v2-${{ github.sha }}-${{ matrix.node }}
test:
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
node: ['22', '24']
name: Build and test on Node ${{ matrix.node }}
node: ["16", "17"]
package: [
# Manually add packages here
detox,
ffmpeg-kit-react-native,
ios-stickers,
react-native-ble-plx,
react-native-blob-util,
react-native-branch,
react-native-google-cast,
react-native-pdf,
# react-native-quick-actions,
]
name: Test ${{ matrix.package }} on Node ${{ matrix.node }}
steps:
- name: 👀 Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/cache@v2
with:
fetch-depth: 1
- name: 🔨 Install pnpm
uses: pnpm/setup@703c52620218391530e48b9e8870d5c0082e1b9b # v2.1.0
with:
install: false
- name: 🔨 Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
path: "*"
key: v2-${{ github.sha }}-${{ matrix.node }}
- name: Set up Node
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Install packages
run: pnpm install --frozen-lockfile
- name: Build all packages
run: pnpm --filter './packages/*' run build
- name: Lint all packages
run: pnpm --filter './packages/*' run lint --deny-warnings
- name: Check formatting
run: pnpm format --check
- name: Test all packages
run: pnpm --filter './packages/*' run test --passWithNoTests
- name: Lint ${{ matrix.package }}
run: yarn lint --max-warnings 0
working-directory: packages/${{ matrix.package }}
- name: Test ${{ matrix.package }}
run: yarn test
working-directory: packages/${{ matrix.package }}
env:
CI: true
EXPO_DEBUG: true
+2 -6
View File
@@ -9,7 +9,7 @@ web-build
# Node
node_modules
npm-debug.log
pnpm-debug.log
yarn-error.log
# Ruby
.direnv
@@ -48,9 +48,6 @@ xcuserdata
.project
.settings
# WebStorm
.idea
# VSCode
.history/
@@ -65,5 +62,4 @@ packages/@*/*/build/**
apps/*/ios/*
apps/*/android/*
apps/*/web-build/*
apps/*/dist/*
apps/*/web-build/*
-30
View File
@@ -1,30 +0,0 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"bracketSameLine": true,
"trailingComma": "es5",
"ignorePatterns": [
"**/node_modules/**",
"**/build/**",
"**/dist/**",
"**/__generated__/**",
"**/fixtures/**",
"**/.expo/**",
"**/assets/**",
"**/android/**",
"**/ios/**",
"**/expo-env.d.ts",
"packages/apple-settings/src/schema/SettingsPlist.ts"
],
"sortImports": {
"groups": [
["builtin", "external"],
["internal", "subpath"],
["parent", "sibling", "index"],
"unknown"
],
"ignoreCase": false
}
}
+62
View File
@@ -0,0 +1,62 @@
// From @byCedric https://github.com/expo/expo-github-action/blob/main/.releaserc.js
const rules = [
{ type: "feat", release: "minor", title: "Features" },
{ type: "fix", release: "patch", title: "Bug Fixes" },
{ type: "test", release: "patch", title: "Tests" },
{ type: "ci", release: "patch", title: "Continuous Integration" },
{ type: "refactor", release: "patch", title: "Code Refactoring" },
{ type: "chore", release: "patch", title: "Other chores" },
{ type: "docs", release: "patch", title: "Documentation changes" },
];
// Simple mapping to order the commit groups
const sortMap = Object.fromEntries(
rules.map((rule, index) => [rule.title, index])
);
module.exports = {
branches: ["main"],
tagFormat: "${version}",
repositoryUrl: "https://github.com/expo/config-plugins.git",
plugins: [
[
"@semantic-release/commit-analyzer",
{
preset: "conventionalcommits",
releaseRules: [
{ breaking: true, release: "major" },
{ revert: true, release: "patch" },
].concat(
rules.map(({ type, release, breaking }) => ({
type,
release,
breaking,
}))
),
},
],
[
"@semantic-release/release-notes-generator",
{
preset: "conventionalcommits",
presetConfig: {
types: rules.map(({ type, title }) => ({ type, section: title })),
},
writerOpts: {
commitGroupsSort: (a, z) => sortMap[a.title] - sortMap[z.title],
},
},
],
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/git",
{
message: "chore: ${nextRelease.version}\n\n${nextRelease.notes}",
assets: ["package.json", "CHANGELOG.md", "build/*"],
},
],
"@semantic-release/github",
],
};
-107
View File
@@ -1,107 +0,0 @@
# CLAUDE.md
## Project Overview
Monorepo of community-maintained Expo config plugins for React Native libraries. Plugins auto-configure native Android/iOS projects during `npx expo prebuild`.
- **Namespace**: `@config-plugins/*`
- **Package manager**: pnpm 12 with workspaces (version pinned in `devEngines.packageManager` in the root `package.json`)
- **Publishing**: `pnpm publish` (independent versioning)
## Common Commands
```bash
# Install dependencies
pnpm install
# Build all packages
pnpm prepare
# Watch build all packages
pnpm start
# Generate a new plugin
pnpm gen
# Run tests for a specific package
cd packages/<name> && pnpm test
# Lint a specific package
cd packages/<name> && pnpm lint --deny-warnings
# Format the whole repo (add --check to only verify)
pnpm format
# Build a specific package
cd packages/<name> && pnpm build
# Clean a specific package
cd packages/<name> && pnpm clean
# Rebuild an example app to test config plugins
cd apps/<name> && pnpm expo prebuild --clean
```
## Project Structure
- `packages/` — Config plugin packages (each has `src/`, `__tests__/`)
- `apps/` — Example apps for testing plugins
- `fixtures/` — Shared test fixtures (native config files: AppDelegate, build.gradle, Podfile, etc.)
- `scripts/` — Repo tooling (plugin generator, dependabot config, issue templates)
## Conventions
- Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) (e.g., `feat(react-native-foo): add bar`)
- Branch naming: `@your-github-username/type/description`
- Each package runs `tsc`, `jest` and `oxlint` directly. Shared config lives at the root: `tsconfig.base.json`, `jest.config.base.js`, `oxlint.config.mjs`. Formatting is `oxfmt` with `.oxfmtrc.json`
- TypeScript source in `src/`, compiled output in `build/`
- Shared dependency versions are defined in the `catalog:` block in `pnpm-workspace.yaml` and referenced with `catalog:` in each package's `package.json`
- Peer dependency on `expo@^56`
- Tests use Jest with `memfs` for virtual filesystem testing
## Upgrading Plugins for a New Expo SDK Version
When a new Expo SDK is released (e.g., SDK 54 → SDK 55), every package and example app must be updated. Use conventional commits scoped to the package name (e.g., `chore(react-native-foo): bump to expo@^55`).
### Catalog updates (`pnpm-workspace.yaml`)
Update the `catalog:` block with the new SDK versions for shared dependencies:
1. **`expo`** — Update to `^<NEW_SDK>` (used as `peerDependencies` in all packages).
2. **`@expo/config-plugins`** — Update to `^<NEW_SDK>`.
3. Review other catalog entries (`@expo/image-utils`, `@expo/plist`, etc.) and bump if needed.
### Per-package updates (`packages/<name>/`)
For each package:
1. **`README.md`** — Add a new row to the version compatibility table with the new SDK version, the latest compatible upstream package version, and the next config plugin major version.
2. **Build & test** — Run `pnpm build` and `pnpm test` (if tests exist) to verify nothing broke.
### Example app updates (`apps/<name>/`)
For each example app:
1. **`package.json`** — Update `expo` to the new SDK version (e.g., `~54` → `~55`).
2. Run `npx expo install --fix` to align all other dependencies (`react`, `react-native`, `expo-splash-screen`, etc.) to compatible versions.
3. Remove any stale vendored templates or files (e.g., old `expo-template-bare-minimum-*.tgz`).
### Monorepo root updates
1. **`scripts/generate-plugin.ts`** — Update `SDK_VERSION` to the new SDK number.
### Final steps
1. Run `pnpm install` from the root to regenerate `pnpm-lock.yaml`.
2. Run `pnpm prepare` to verify all packages build.
3. Run tests for packages that have them.
4. Update `CLAUDE.md` if any conventions changed (e.g., the peer dependency version listed under Conventions).
## After Adding/Removing Packages
Run these from the root:
```bash
pnpm update-dependabot-config
pnpm update-issue-template
```
+6 -19
View File
@@ -5,36 +5,23 @@
To submit a pull request:
1. Fork the [repository](https://github.com/expo/config-plugins) and create a feature branch. (Existing contributors can create feature branches without forking. Prefix the branch name with `@your-github-username/`.)
2. Run `pnpm install` in the root directory to generate the build files.
3. Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) including in the PR title.
2. Run `yarn` in the root directory to generate the build files.
3. Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) including in the PR tile.
4. Fill out the entire PR template. Ensure your code is tested locally and has continuous tests in CI.
5. Make sure all tests pass on GitHub Actions.
6. Wait for a review and adjust the code if necessary.
## Creating a plugin
- Plugins can be generated by running `pnpm gen`.
- Plugins can be generated by running `yarn gen`.
- Add plugins to the example in [`apps/app`](/apps/app/package.json) to test them.
- The example app should always stay in a state of regeneration.
Be sure to run the following scripts in the **root directory** to update automation tools:
- Update dependabot: `pnpm update-dependabot-config`
- Update the issue template: `pnpm update-issue-template`
## Upgrading plugins for a new Expo version
- Update the `catalog:` block in `pnpm-workspace.yaml` with the new SDK versions for `expo`, `@expo/config-plugins`, and any other shared dependencies
- Ensure every project under `apps/` is updated to latest version of Expo
- Update each library’s `README.md`
- Ensuring the latest version of Expo is listed
- Ensure the upstream package version is correct
- Use the next version for the matching config plugin
- Update `SDK_VERSION` in [`scripts/generate-plugin.ts`](https://github.com/expo/config-plugins/blob/566f54e785147d88cb4c98490c3e536ee7ef3001/scripts/generate-plugin.ts#L67)
- Update dependabot: `yarn update-dependabot-config`
- Update the issue template: `yarn update-issue-template`
## Publishing a release
Packages are published manually using the scripts in the root `package.json`:
1. `pnpm bump`: Increments the major version of all packages.
2. `pnpm release`: Publishes all packages to npm.
All publishing should be handled automatically whenever code is merged to `main`.
+5 -11
View File
@@ -1,16 +1,10 @@
# Expo Config Plugins
This repository is a collection of assorted [Expo config plugins](https://docs.expo.dev/guides/config-plugins/) for configuring the `npx expo prebuild` command. It is meant to be a temporary home for packages that don't have a built-in Config Plugin.
- **We prefer packages to ship their own Expo config plugin**. This helps ensure that plugin and package versions are always aligned, and that new features are made available in both the package and plugin simultaneously. If packages haven't adopted config plugins yet, the community can add a package here as a temporary home.
- **All packages here are community maintained.** They are not maintained by Expo. Feel free to improve docs, packages, tests, etc.
- **We maintain a one-to-one mapping between native packages and `@config-plugins/*`**. This means there should be no general utility packages here — those are better suited for a different repository or npm namespace.
## Looking for other config plugins?
Many React Native libraries ship their own built-in config plugins. You can find them on the [React Native Directory](https://reactnative.directory/).
- A collection of [Expo config plugins](https://docs.expo.dev/guides/config-plugins/) for configuring the `expo prebuild` command.
- This repo is to Expo config plugins as [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) is to TypeScript.
- We prefer packages ship their own Expo config plugin (to ensure versioning is aligned), but if they haven't adopted the system yet, the community can add a package here.
- All packages here are community maintained. Feel free to improve docs, packages, tests, etc.
- We maintain a 1-1 mapping of **native packages** ⇔ `@config-plugins/*`. This means there should be no general utility packages here -- those are better suited for a different repo / NPM namespace.
## Contributing!
@@ -0,0 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
Whitespace-only changes.
@@ -1,7 +1,7 @@
const path = require('path');
const path = require("path");
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, '');
const appId = 'dev.bacon.' + cleanName;
const cleanName = folderName.replace(/[_\s-]/g, "");
const appId = "dev.bacon." + cleanName;
module.exports = ({ config }) => {
if (!config.extra) config.extra = {};
+8
View File
@@ -0,0 +1,8 @@
{
"expo": {
"icon": "https://icogen.vercel.app/api/icon?icon=1f334",
"plugins": [
"@config-plugins/airbridge-react-native-sdk"
]
}
}
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+5
View File
@@ -0,0 +1,5 @@
import { registerRootComponent } from "expo";
import App from "./src/App";
registerRootComponent(App);
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
@@ -0,0 +1,25 @@
{
"name": "@config-plugins-app/airbridge-react-native-sdk",
"main": "./index.js",
"version": "1.0.0",
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/airbridge-react-native-sdk": "*",
"expo": "^45.0.0",
"expo-splash-screen": "~0.15.1",
"react": "17.0.2",
"react-native": "0.68.2",
"airbridge-react-native-sdk": "^1.4.5",
"expo-status-bar": "~1.3.0",
"react-dom": "17.0.2",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9"
},
"private": true
}
@@ -0,0 +1,10 @@
import React from "react";
import { Text, View } from "react-native";
export default function App() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>airbridge-react-native-sdk</Text>
</View>
);
}
+4
View File
@@ -0,0 +1,4 @@
{
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
+79 -1
View File
@@ -1,2 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/artifacts
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
+3 -1
View File
@@ -1 +1,3 @@
export { default } from './src/react-native-adjust/App';
export { default } from './src/detox/App';
// export { default } from './src/android-jsc-intl/App';
// export { default } from './src/android-jsc-adjust/App';
+66
View File
@@ -0,0 +1,66 @@
### @expo/app [1.0.1](https://github.com/expo/config-plugins/compare/@expo/[email protected]...@expo/[email protected]) (2022-03-15)
### Bug Fixes
* **ci:** use correct internal versions ([ab8076a](https://github.com/expo/config-plugins/commit/ab8076adf51e9ba0439eba60b153d729a0996b8d))
### Dependencies
* **@config-plugins/android-jsc-intl:** upgraded to 1.0.1
* **@config-plugins/detox:** upgraded to 1.0.1
* **@config-plugins/react-native-adjust:** upgraded to 1.0.0
* **@config-plugins/react-native-ble-plx:** upgraded to 1.0.0
* **@config-plugins/react-native-blob-util:** upgraded to 1.0.1
* **@config-plugins/react-native-branch:** upgraded to 1.0.0
* **@config-plugins/react-native-callkeep:** upgraded to 1.0.0
* **@config-plugins/react-native-dynamic-app-icon:** upgraded to 1.0.0
* **@config-plugins/react-native-google-cast:** upgraded to 1.0.0
* **@config-plugins/react-native-pdf:** upgraded to 1.0.0
* **@config-plugins/react-native-quick-actions:** upgraded to 1.0.0
* **@config-plugins/react-native-webrtc:** upgraded to 1.0.0
## @expo/app 1.0.0 (2022-03-15)
### Features
* create react-native-branch plugin ([0b06baa](https://github.com/expo/config-plugins/commit/0b06baa2b486c5e02d433a4ac785960934f403b9))
### Bug Fixes
* respect old config from expo-branch ([d0e0186](https://github.com/expo/config-plugins/commit/d0e018601c09c0e92191a4eb2998ab0e6fa1c6ec))
### Other chores
* added start-metro script ([4a7d707](https://github.com/expo/config-plugins/commit/4a7d707b200a3e499d9d71caf49ad4fc1d0a89e0))
* update script ([dcf61a9](https://github.com/expo/config-plugins/commit/dcf61a9b9542851095954d84c9054c97c5400dc9))
* upgrade to latest react-native-branch ([df98474](https://github.com/expo/config-plugins/commit/df98474d79ed139b42ddd698d13100160c656c26))
### Documentation changes
* add android-jsc-intl example ([d96c0b2](https://github.com/expo/config-plugins/commit/d96c0b2888da3808d7c4e2dd7993129711ba717d))
### Dependencies
* **@config-plugins/android-jsc-intl:** upgraded to 1.0.0
* **@config-plugins/detox:** upgraded to 1.0.0
* **@config-plugins/ffmpeg-kit-react-native:** upgraded to 1.0.0
* **@config-plugins/ios-stickers:** upgraded to 1.0.0
* **@config-plugins/react-native-adjust:** upgraded to 1.0.0
* **@config-plugins/react-native-ble-plx:** upgraded to 1.0.0
* **@config-plugins/react-native-blob-util:** upgraded to 1.0.0
* **@config-plugins/react-native-branch:** upgraded to 1.0.0
* **@config-plugins/react-native-callkeep:** upgraded to 1.0.0
* **@config-plugins/react-native-dynamic-app-icon:** upgraded to 1.0.0
* **@config-plugins/react-native-google-cast:** upgraded to 1.0.0
* **@config-plugins/react-native-pdf:** upgraded to 1.0.0
* **@config-plugins/react-native-quick-actions:** upgraded to 1.0.0
* **@config-plugins/react-native-webrtc:** upgraded to 1.0.0
+5 -2
View File
@@ -4,7 +4,7 @@
"slug": "app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "https://github.com/expo.png",
"icon": "https://icogen.vercel.app/api/icon",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
@@ -29,9 +29,12 @@
"favicon": "./assets/favicon.png"
},
"plugins": [
"@config-plugins/react-native-adjust",
"@config-plugins/react-native-callkeep",
"expo-localization"
"@config-plugins/react-native-blob-util",
"@config-plugins/react-native-pdf",
"@config-plugins/android-jsc-intl"
]
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+72
View File
@@ -0,0 +1,72 @@
const iosName = "app";
const emulator = "Pixel_3a_API_30";
const simulator = "iPhone 13 Pro";
const derivedDataPath = "ios/build";
const sdk = "iphonesimulator";
module.exports = {
testRunner: "jest",
runnerConfig: require.resolve("./e2e/jest.config.js"),
specs: "e2e",
behavior: {
init: {
exposeGlobals: false,
},
},
apps: {
"ios.release": {
type: "ios.app",
binaryPath: `${derivedDataPath}/Build/Products/Release-${sdk}/${iosName}.app`,
build: `./scripts/build-detox-ios.sh ${iosName} Release YES`,
},
"ios.debug": {
type: "ios.app",
binaryPath: `${derivedDataPath}/Build/Products/Debug-${sdk}/${iosName}.app`,
build: `./scripts/start-metro.sh && ./scripts/build-detox-ios.sh ${iosName} Debug`,
},
"android.debug": {
type: "android.apk",
binaryPath: "android/app/build/outputs/apk/debug/app-debug.apk",
build:
"./scripts/start-metro.sh && pushd android; ./gradlew app:assembleDebug app:assembleAndroidTest -DtestBuildType=debug; popd",
},
"android.release": {
type: "android.apk",
binaryPath: "android/app/build/outputs/apk/release/app-release.apk",
build:
"pushd android; ./gradlew app:assembleRelease app:assembleAndroidTest -DtestBuildType=release; popd",
},
},
devices: {
simulator: {
type: "ios.simulator",
device: {
type: simulator,
},
},
emulator: {
type: "android.emulator",
device: {
avdName: emulator,
},
},
},
configurations: {
"ios.sim.release": {
device: "simulator",
app: "ios.release",
},
"ios.sim.debug": {
device: "simulator",
app: "ios.debug",
},
"android.emu.debug": {
device: "emulator",
app: "android.debug",
},
"android.emu.release": {
device: "emulator",
app: "android.release",
},
},
};
+39
View File
@@ -0,0 +1,39 @@
import { by, device, element, expect } from "detox";
import * as path from "path";
import { createCapture } from "../lib";
const projectRoot = path.resolve(__dirname, "../../");
// https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html
const languages = ["en-US", "nl-NL", "zh-CN"];
for (const locale of languages) {
const { captureAsync, resetAppAsync } = createCapture({
projectRoot,
locale,
});
describe(locale, () => {
beforeAll(resetAppAsync);
beforeEach(async () => {
await device.reloadReactNative();
});
it("should have welcome screen", async () => {
await expect(element(by.id("welcome"))).toBeVisible();
await captureAsync();
});
xit("should show hello screen after tap", async () => {
await element(by.id("hello_button")).tap();
await captureAsync();
});
xit("should show world screen after tap", async () => {
await element(by.id("world_button")).tap();
await captureAsync();
});
});
}
+23
View File
@@ -0,0 +1,23 @@
const {
DetoxCircusEnvironment,
SpecReporter,
WorkerAssignReporter,
} = require("detox/runners/jest-circus");
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config, context) {
super(config, context);
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
});
}
}
module.exports = CustomDetoxEnvironment;
+11
View File
@@ -0,0 +1,11 @@
module.exports = {
testEnvironment: require.resolve("./environment.js"),
testRunner: require.resolve("jest-circus/runner"),
testTimeout: 120000,
testRegex: "/__tests__/.*(e2e)\\.[jt]sx?$",
transform: {
"^.+\\.[jt]sx?$": "ts-jest",
},
reporters: [require.resolve("detox/runners/jest/streamlineReporter")],
verbose: true,
};
+76
View File
@@ -0,0 +1,76 @@
import { device } from "detox";
import * as fs from "fs";
import * as path from "path";
import { setStatusBar } from "./setStatusBar";
export function getOutputDir(projectRoot: string, locale: string) {
return path.resolve(
projectRoot,
`meta/screenshots/${device.getPlatform()}/${locale}/`
);
}
export async function takeScreenshotAsync({
info,
projectRoot,
index,
locale,
}: {
projectRoot: string;
locale: string;
info?: string;
index?: number;
}) {
const outputDir = getOutputDir(projectRoot, locale);
fs.mkdirSync(outputDir, { recursive: true });
if (index == null) {
index = fs.readdirSync(outputDir).length;
}
const name = `APP_${device.name}_${index}`.toUpperCase();
const imgPath = path.resolve(outputDir, `${name}.png`);
const imagePath = await device.takeScreenshot(name);
await fs.promises.copyFile(imagePath, imgPath);
}
export function createCapture({
projectRoot,
locale,
}: {
locale: string;
projectRoot: string;
}) {
const captureAsync = () =>
takeScreenshotAsync({
projectRoot,
locale,
});
const clearAsync = async () => {
// Clear old screen shots
const outputDir = getOutputDir(projectRoot, locale);
await fs.promises.rmdir(outputDir, { recursive: true }).catch(() => null);
};
return {
captureAsync,
clearAsync,
async resetAppAsync() {
// Clear old screen shots
await clearAsync();
// configure status bars
setStatusBar();
// reset expo-localization which doesn't account for simulators dynamically updating without resetting the phone.
await device.terminateApp();
// launch with lang
await device.launchApp({
languageAndLocale: { locale, language: locale },
launchArgs: { locale },
});
},
};
}
+32
View File
@@ -0,0 +1,32 @@
import { execSync } from "child_process";
import { device } from "detox";
export async function setStatusBar() {
if (device.getPlatform() === "ios") {
// TODO: Set date on iPad - "Tue Jan 9"
// assumes only one simulator is booted
// use Apple's magic time "9:41" - new Date('1/9/2007 09:41').toISOString()
execSync(
"xcrun simctl status_bar booted override --time 9:41 --batteryState charged --batteryLevel 100 --wifiBars 3 --cellularMode active --cellularBars 4"
);
} else {
// enter demo mode
execSync("adb shell settings put global sysui_demo_allowed 1");
// display time 6:00
execSync(
"adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1850"
);
// Display full mobile data with 4g type and no wifi
execSync(
"adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 4 -e datatype 4g -e wifi false"
);
// Hide notifications
execSync(
"adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false"
);
// Show full battery but not in charging state
execSync(
"adb shell am broadcast -a com.android.systemui.demo -e command battery -e plugged false -e level 100"
);
}
}
+11 -2
View File
@@ -1,6 +1,15 @@
import { registerRootComponent } from 'expo';
import { registerRootComponent } from "expo";
import App from './App';
import Constants from "expo-constants";
let App;
// Only use the Detox test in CI
if ((Constants.manifest.extra || {}).CI) {
App = require("./src/detox/App").default;
} else {
App = require("./App").default;
}
// import App from "./App";
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

+6
View File
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
+44 -19
View File
@@ -1,36 +1,61 @@
{
"name": "@expo/app",
"version": "1.0.0",
"private": true,
"main": "./index.js",
"version": "1.0.0",
"scripts": {
"build:ios": "detox build -c ios.sim.debug",
"test:ios": "detox test -c ios.sim.debug",
"e2e:ios": "npm run build:ios && npm run test:ios",
"build:ios-release": "detox build -c ios.sim.release",
"test:ios-release": "detox test -c ios.sim.release",
"e2e:ios-release": "npm run build:ios-release && npm run test:ios-release",
"build:android": "detox build -c android.emu.debug",
"test:android": "detox test -c android.emu.debug",
"e2e:android": "npm run build:android && npm run test:android",
"build:android-release": "detox build -c android.emu.release",
"test:android-release": "detox test -c android.emu.release",
"e2e:android-release": "npm run build:android-release && npm run test:android-release",
"clean:android": "pushd android && ./gradlew clean && popd",
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/react-native-adjust": "workspace:*",
"@config-plugins/react-native-callkeep": "workspace:*",
"expo": "~56",
"expo-localization": "~56.0.6",
"expo-splash-screen": "~56.0.10",
"@config-plugins/android-jsc-intl": "*",
"@config-plugins/detox": "*",
"@config-plugins/react-native-adjust": "*",
"@config-plugins/react-native-callkeep": "*",
"expo": "^45.0.0",
"detox": "^19.6.9",
"expo-localization": "~13.0.0",
"expo-splash-screen": "~0.15.1",
"expo-status-bar": "~1.3.0",
"expo-updates": "~0.13.1",
"fbjs": "^0.8.18",
"i18n-js": "^3.8.0",
"luxon": "^1.27.0",
"react": "19.2.3",
"react-native": "0.85.3",
"react-native-adjust": "^5.6.0",
"react-native-callkeep": "^4.3.16",
"react-native-safe-area-context": "~5.7.0"
"react": "17.0.2",
"react-dom": "17.0.2",
"react-native": "0.68.2",
"react-native-adjust": "^4.29.6",
"react-native-callkeep": "^4.3.3",
"react-native-safe-area-context": "4.2.4",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/plugin-syntax-jsx": "^7.16.0",
"@types/jest": "^29.4.0",
"@expo/metro-config": "~0.3.7",
"@expo/xcpretty": "^4.1.2",
"@types/jest": "^26.0.19",
"@types/luxon": "^1.27.1",
"babel-jest": "^29.5.0",
"jest": "~29.7.0",
"jest-circus": "^29.5.0",
"ts-jest": "^29.0.5",
"typescript": "~5.9.2"
}
"@types/react": "~17.0.21",
"@types/react-native": "~0.64.12",
"babel-jest": "~25.2.6",
"jest": "^26.6.3",
"jest-circus": "^26.5.2",
"ts-jest": "^26.4.4",
"typescript": "~4.3.5"
},
"private": true
}
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# This script wraps the xcodebuild command and exits with non-zero if the build fails.
#
# This ensures that CI fails on the correct step instead of attempting to run Detox tests without a
# build.
set -eu
iosName=$1
# Debug or Release
configuration=$2
# YES or NO
UseModernBuildSystem=${3:-"NO"}
xcodebuild \
-workspace ios/$iosName.xcworkspace \
-scheme $iosName \
-configuration "$configuration" \
-sdk iphonesimulator \
-derivedDataPath "ios/build" \
-UseModernBuildSystem="$UseModernBuildSystem" 2>&1 | npx excpretty ./
if [ "${PIPESTATUS[0]}" -ne "0" ]; then
echo 'Build Failed'
set +e
exit 1
fi
echo 'Build Succeeded'
+1 -1
View File
@@ -16,7 +16,7 @@ else
commandFile=$(dirname "$0")/start.command
cat > ${commandFile} << EOF
cd "\$(dirname "\$0")/.."
# Run 'npx expo start --help' to get more parameters
# Run 'react-native start --help' to get more parameters
yarn start --port ${port}
EOF
# execute the file in a new command line window
+28
View File
@@ -0,0 +1,28 @@
import React from "react";
import { Text, View } from "react-native";
import { DateTime } from "luxon";
const currentDate = DateTime.fromObject({
locale: "en-US",
zone: "America/New_York",
});
export default function App() {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "blue",
}}
>
<Text style={{ fontSize: 18, color: "white", textAlign: "center" }}>
Intl support for Android, without Hermes 🤖
</Text>
<Text style={{ fontSize: 18, color: "white", textAlign: "center" }}>
{currentDate.toISO()}
</Text>
</View>
);
}
+62
View File
@@ -0,0 +1,62 @@
import React from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import * as Localization from "expo-localization";
import i18n from "i18n-js";
// Set the key-value pairs for the different languages you want to support.
i18n.translations = {
"en-US": { welcome: "Welcome", hello: "Hello", world: "World" },
"nl-NL": { welcome: "Welkom", hello: "Hallo", world: "Wereld" },
"zh-CN": { welcome: "欢迎", hello: "你好", world: "世界" },
};
// Set the locale once at the beginning of your app.
i18n.locale = Localization.locale;
export default function App() {
const [greeting, setGreeting] = React.useState("");
if (greeting) {
return (
<View style={styles.container}>
<Text style={styles.text}>{greeting}!!!</Text>
</View>
);
}
return (
<View testID="welcome" style={styles.container}>
<Text style={styles.text}>
{i18n.t("welcome")} {JSON.stringify(Localization.locales)}
</Text>
<TouchableOpacity
testID="hello_button"
onPress={() => setGreeting(i18n.t("hello"))}
>
<Text style={styles.buttonText}>Say {i18n.t("hello")}</Text>
</TouchableOpacity>
<TouchableOpacity
testID="world_button"
onPress={() => setGreeting(i18n.t("world"))}
>
<Text style={styles.buttonText}>Say {i18n.t("world")}</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20,
justifyContent: "center",
alignItems: "center",
},
text: {
fontSize: 25,
marginBottom: 30,
},
buttonText: {
color: "blue",
marginBottom: 20,
},
});
+10 -8
View File
@@ -1,12 +1,14 @@
import React from 'react';
import { SafeAreaView, Text, StyleSheet } from 'react-native';
import { Adjust, AdjustConfig } from 'react-native-adjust';
import React from "react";
import { SafeAreaView, Text, StyleSheet } from "react-native";
import { Adjust, AdjustConfig } from "react-native-adjust";
export default function App() {
React.useEffect(() => {
// https://github.com/adjust/react_native_sdk/blob/bd4fe59403a57599767606b2bcaa116852df973d/example/App.js#L45
const adjustConfig = new AdjustConfig('APP_TOKEN', AdjustConfig.EnvironmentSandbox);
Adjust.enable();
const adjustConfig = new AdjustConfig(
"APP_TOKEN",
AdjustConfig.EnvironmentSandbox
);
Adjust.create(adjustConfig);
}, []);
return (
@@ -19,7 +21,7 @@ export default function App() {
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
justifyContent: "center",
alignItems: "center",
},
});
+3
View File
@@ -0,0 +1,3 @@
const { createWebpackConfigAsync } = require("expo-yarn-workspaces/webpack");
module.exports = createWebpackConfigAsync;
-49
View File
@@ -1,49 +0,0 @@
appId: dev.bacon.applesettings
---
# Kill the Settings app to ensure a clean state
- killApp: 'com.apple.Preferences'
# Launch the app
- launchApp
# Verify main UI elements are visible
- assertVisible:
id: 'name-input'
- assertVisible:
id: 'enabled-switch'
- assertVisible:
id: 'slider'
# Clear any existing text and type a new value
- tapOn:
id: 'name-input'
- eraseText: 50
- inputText: 'Maestro'
# Toggle the switch on (default is off)
- tapOn:
id: 'enabled-switch'
# Open iOS Settings for this app
- tapOn: 'Launch Settings'
# Navigate to the app's settings page
- scrollUntilVisible:
element: 'Apps'
direction: DOWN
- tapOn: 'Apps'
- scrollUntilVisible:
element: 'apple-settings'
direction: DOWN
- tapOn: 'apple-settings'
- scrollUntilVisible:
element: 'apple-settings Settings'
direction: DOWN
# Verify updated values in the iOS Settings app
- assertVisible: 'Maestro'
# Verify the Enabled toggle is on (checked = true when on)
- assertVisible:
id: 'PSToggleSwitchSpecifier.enabled_preference.Enabled'
checked: true
-123
View File
@@ -1,123 +0,0 @@
import withAppleSettings, {
ChildPane,
Group,
RadioGroup,
Slider,
Switch,
TextField,
Title,
} from '@config-plugins/apple-settings';
import { MultiValue } from '@config-plugins/apple-settings/build/models';
import { ConfigContext, ExpoConfig } from 'expo/config';
import path from 'node:path';
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, '');
const appId = 'dev.bacon.' + cleanName;
function withWhiteLabel(config: Partial<ExpoConfig>) {
if (!config.extra) config.extra = {};
// Expose CI env variables to the app
config.extra.CI = process.env.CI;
if (!config.ios) config.ios = {};
config.ios.bundleIdentifier = appId;
if (!config.android) config.android = {};
config.android.package = appId;
return config;
}
module.exports = ({ config }: ConfigContext): Partial<ExpoConfig> => {
config = withWhiteLabel(config);
config = withAppleSettings(config as ExpoConfig, {
// The name of the .plist file to generate. Root is the default and must be provided.
Root: {
// The locales object is optional. If provided, it will be used to generate the localized .strings files.
locales: {
// The Apple locale code. This will be used to generate the .strings file.
en: {
// Name of the localized key.
Name: 'Text Field',
},
},
// The page object is required. It will be used to generate the .plist file.
// The contents will be converted directly to plist.
page: {
// The `PreferenceSpecifiers` defines the UI elements to generate.
PreferenceSpecifiers: [
Title({
title: 'Title',
value: 'Default Title',
key: 'title_preference',
}),
// Helper models can be used to generate the UI elements using
// an API that's similar to React Native.
TextField({
title: 'Name',
key: 'name_preference',
value: '',
keyboardType: 'Alphabet',
autoCapitalize: 'None',
autoCorrect: 'No',
}),
Switch({
title: 'Enabled',
key: 'enabled_preference',
value: true,
}),
Slider({
key: 'slider_preference',
value: 0.5,
}),
// Broken https://forums.developer.apple.com/forums/thread/764519
// RadioGroup({
// value: "option1",
// key: "radio_preference",
// items: [
// {
// title: "Option 1",
// value: "option1",
// },
// {
// title: "Option 2",
// value: "option2",
// },
// ],
// }),
// MultiValue({
// title: "Multi Value",
// key: "multi_value_preference",
// value: "alpha",
// items: [
// {
// title: "Alpha",
// value: "alpha",
// short: "α",
// },
// {
// title: "Beta",
// value: "beta",
// short: "β",
// },
// {
// title: "Delta",
// value: "delta",
// short: "Δ",
// },
// {
// title: "Omega",
// value: "omega",
// short: "Ω",
// },
// ],
// }),
],
},
},
});
return config;
};
-7
View File
@@ -1,7 +0,0 @@
{
"expo": {
"name": "apple-settings",
"icon": "https://github.com/expo.png",
"platforms": ["ios"]
}
}
-5
View File
@@ -1,5 +0,0 @@
import { registerRootComponent } from 'expo';
import App from './src/App';
registerRootComponent(App);
-21
View File
@@ -1,21 +0,0 @@
{
"name": "@config-plugins-app/apple-settings",
"version": "1.0.0",
"private": true,
"main": "./index.js",
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android",
"e2e": "maestro test .maestro/"
},
"dependencies": {
"@config-plugins/apple-settings": "workspace:*",
"@react-native-community/slider": "5.2.0",
"@react-native-picker/picker": "2.11.4",
"expo": "~56",
"expo-splash-screen": "~56.0.10",
"react": "19.2.3",
"react-native": "0.85.3"
}
}
-59
View File
@@ -1,59 +0,0 @@
import React from 'react';
import { Button, Linking, StyleSheet, View } from 'react-native';
import {
SettingsRadioGroup,
SettingsSlider,
SettingsSwitch,
SettingsTextInput,
SettingsTitle,
} from './SettingsViews';
const App = () => {
return (
<View style={styles.container}>
{/* <SettingsTitle settingsKey="title_preference" /> */}
<SettingsTextInput
testID="name-input"
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
padding: 8,
}}
settingsKey="name_preference"
/>
<SettingsSwitch testID="enabled-switch" settingsKey="enabled_preference" />
<SettingsSlider testID="slider" settingsKey="slider_preference" />
<View />
{/* Broken https://forums.developer.apple.com/forums/thread/764519 */}
{/*<SettingsRadioGroup settingsKey="radio_preference">*/}
{/* <SettingsRadioGroup.Item label="Option 1" value="option1" />*/}
{/* <SettingsRadioGroup.Item label="Option 2" value="option2" />*/}
{/*</SettingsRadioGroup>*/}
<View />
<Button
title="Launch Settings"
onPress={() => {
void Linking.openSettings();
}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
paddingHorizontal: 56,
gap: 12,
},
value: {
fontSize: 24,
marginVertical: 12,
},
});
export default App;
-79
View File
@@ -1,79 +0,0 @@
import Slider from '@react-native-community/slider';
import { Picker } from '@react-native-picker/picker';
import React from 'react';
import { Settings, Switch, Text, TextInput } from 'react-native';
export function useSetting<T = string>(key: string): [T, (value: T) => void] {
const [value, setValue] = React.useState<T>(() => Settings.get(key));
React.useEffect(() => {
let isMounted = true;
const callback = Settings.watchKeys(key, () => {
if (isMounted) {
setValue(Settings.get(key));
}
});
return () => {
Settings.clearWatch(callback);
isMounted = false;
};
}, [key]);
return [
value,
(value) => {
Settings.set({ [key]: value });
setValue(value);
},
];
}
export function SettingsSlider({
settingsKey,
...props
}: { settingsKey: string } & Omit<
React.ComponentProps<typeof Slider>,
'selectedValue' | 'onValueChange'
>) {
const [value, setValue] = useSetting<number>(settingsKey);
return <Slider {...props} value={value ?? 0} onValueChange={setValue} />;
}
export function SettingsRadioGroup({
settingsKey,
...props
}: { settingsKey: string } & Omit<
React.ComponentProps<typeof Picker>,
'selectedValue' | 'onValueChange'
>) {
const [value, setValue] = useSetting<string>(settingsKey);
return <Picker {...props} selectedValue={value ?? 'option1'} onValueChange={setValue} />;
}
SettingsRadioGroup.Item = Picker.Item;
export function SettingsSwitch({
settingsKey,
...props
}: { settingsKey: string } & Omit<React.ComponentProps<typeof Switch>, 'value' | 'onValueChange'>) {
const [value, setValue] = useSetting<boolean>(settingsKey);
return <Switch {...props} value={!!value} onValueChange={setValue} />;
}
export function SettingsTitle({
settingsKey,
...props
}: { settingsKey: string } & Omit<React.ComponentProps<typeof Text>, 'children'>) {
const [value] = useSetting<string>(settingsKey);
return <Text {...props} children={value} />;
}
export function SettingsTextInput({
settingsKey,
...props
}: { settingsKey: string } & Omit<
React.ComponentProps<typeof TextInput>,
'value' | 'onChangeText'
>) {
const [value, setValue] = useSetting<string>(settingsKey);
return <TextInput {...props} value={value} onChangeText={setValue} />;
}
+80
View File
@@ -0,0 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
Whitespace-only changes.
@@ -0,0 +1,16 @@
const path = require("path");
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, "");
const appId = "dev.bacon." + cleanName;
module.exports = ({ config }) => {
if (!config.extra) config.extra = {};
// Expose CI env variables to the app
config.extra.CI = process.env.CI;
if (!config.ios) config.ios = {};
config.ios.bundleIdentifier = appId;
if (!config.android) config.android = {};
config.android.package = appId;
return config;
};
+13
View File
@@ -0,0 +1,13 @@
{
"expo": {
"icon": "https://icogen.vercel.app/api/icon",
"plugins": [
[
"@config-plugins/ffmpeg-kit-react-native",
{
"package": "min"
}
]
]
}
}
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+5
View File
@@ -0,0 +1,5 @@
import { registerRootComponent } from "expo";
import App from "./src/App";
registerRootComponent(App);
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
+25
View File
@@ -0,0 +1,25 @@
{
"name": "@config-plugins-app/ffmpeg-kit-react-native",
"main": "./index.js",
"version": "1.0.0",
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/ffmpeg-kit-react-native": "*",
"expo": "^45.0.0",
"expo-splash-screen": "~0.15.1",
"react": "17.0.2",
"react-native": "0.68.2",
"ffmpeg-kit-react-native": "^4.5.1",
"expo-status-bar": "~1.3.0",
"react-dom": "17.0.2",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9"
},
"private": true
}
+41
View File
@@ -0,0 +1,41 @@
import { Session } from 'ffmpeg-kit-react-native';
import React from 'react';
import { ActivityIndicator, SafeAreaView, ScrollView, Text, View } from 'react-native';
import { useMediaInfo, useResolvedValue } from './useMediaInfo';
export default function App() {
const session = useMediaInfo('http://techslides.com/demos/sample-videos/small.mp4');
if (!session) {
return <View style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}><ActivityIndicator /><Text>Loading...</Text></View>
}
return <SessionInfo session={session} />
}
function SessionInfo(props: { session: Session }) {
const { session } = props;
const duration = useResolvedValue(session.getDuration.bind(session));
const output = useResolvedValue(session.getOutput.bind(session));
return (
<SafeAreaView
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<ScrollView>
<Text>Duration: {duration}</Text>
<Text>Output: {output}</Text>
</ScrollView>
</SafeAreaView>
);
}
@@ -0,0 +1,55 @@
import { FFprobeKit, Session } from "ffmpeg-kit-react-native";
import React from "react";
function useMounted() {
const isMounted = React.useRef(true);
React.useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
}
export function useResolvedValue<T>(
method: () => Promise<T>
): [T | null, Error | null] {
const [error, setError] = React.useState<Error | null>(null);
const [value, setValue] = React.useState<T | null>(null);
React.useEffect(() => {
let isMounted = true;
method()
.then((value) => {
if (isMounted) {
setValue(value);
}
})
.catch((error) => {
if (isMounted) {
setError(error);
}
});
return () => {
isMounted = false;
};
}, []);
return [value, error];
}
export function useMediaInfo(filePathOrUrl: string) {
const [results, setResults] = React.useState<Session | undefined>(undefined);
const isMounted = useMounted();
React.useEffect(() => {
FFprobeKit.getMediaInformationAsync(filePathOrUrl, async (session) => {
if (isMounted) {
setResults(session);
}
});
}, [filePathOrUrl]);
return results;
}
+80
View File
@@ -0,0 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
View File
Whitespace-only changes.
+3 -3
View File
@@ -1,7 +1,7 @@
const path = require('path');
const path = require("path");
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, '');
const appId = 'dev.bacon.' + cleanName;
const cleanName = folderName.replace(/[_\s-]/g, "");
const appId = "dev.bacon." + cleanName;
module.exports = ({ config }) => {
if (!config.extra) config.extra = {};
+1 -4
View File
@@ -1,14 +1,11 @@
{
"expo": {
"name": "stickers",
"icon": "https://github.com/expo.png",
"platforms": ["ios"],
"icon": "https://icogen.vercel.app/api/icon",
"plugins": [
[
"@config-plugins/ios-stickers",
{
"name": "Stickers",
"stickerBundleId": "dev.bacon.iosstickers.stickers",
"icon": "./assets/imessage-icon.png",
"columns": 4,
"stickers": [
+6
View File
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+2 -2
View File
@@ -1,5 +1,5 @@
import { registerRootComponent } from 'expo';
import { registerRootComponent } from "expo";
import App from './src/App';
import App from "./src/App";
registerRootComponent(App);
+6
View File
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
+14 -7
View File
@@ -1,17 +1,24 @@
{
"name": "@config-plugins-app/ios-stickers",
"main": "./index.js",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/ios-stickers": "workspace:*",
"expo": "~56",
"expo-splash-screen": "~56.0.10",
"react": "19.2.3",
"react-native": "0.85.3"
}
"@config-plugins/ios-stickers": "*",
"expo": "^45.0.0",
"expo-splash-screen": "~0.15.1",
"react": "17.0.2",
"react-native": "0.68.2",
"expo-status-bar": "~1.3.0",
"react-dom": "17.0.2",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9"
},
"private": true
}
+3 -2
View File
@@ -1,8 +1,9 @@
import { Text, View } from 'react-native';
import React from "react";
import { Text, View } from "react-native";
export default function App() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Open iMessage to find the app</Text>
</View>
);
-4
View File
@@ -1,4 +0,0 @@
{
"compilerOptions": {},
"extends": "expo/tsconfig.base"
}
+80
View File
@@ -0,0 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
Whitespace-only changes.
+16
View File
@@ -0,0 +1,16 @@
const path = require("path");
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, "");
const appId = "dev.bacon." + cleanName;
module.exports = ({ config }) => {
if (!config.extra) config.extra = {};
// Expose CI env variables to the app
config.extra.CI = process.env.CI;
if (!config.ios) config.ios = {};
config.ios.bundleIdentifier = appId;
if (!config.android) config.android = {};
config.android.package = appId;
return config;
};
+8
View File
@@ -0,0 +1,8 @@
{
"expo": {
"icon": "https://icogen.vercel.app/api/icon?icon=1f9b7&color_hex=0000ff",
"plugins": [
"@config-plugins/react-native-ble-plx"
]
}
}
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+5
View File
@@ -0,0 +1,5 @@
import { registerRootComponent } from "expo";
import App from "./src/App";
registerRootComponent(App);
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
+28
View File
@@ -0,0 +1,28 @@
{
"name": "@config-plugins-app/react-native-ble-plx",
"main": "./index.js",
"version": "1.0.0",
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/react-native-ble-plx": "*",
"expo": "^45.0.0",
"expo-splash-screen": "~0.15.1",
"react": "17.0.2",
"react-native": "0.68.2",
"react-native-ble-plx": "^2.0.3",
"expo-status-bar": "~1.3.0",
"react-dom": "17.0.2",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@types/react": "~17.0.21",
"@types/react-native": "~0.64.12",
"typescript": "~4.3.5"
},
"private": true
}
+32
View File
@@ -0,0 +1,32 @@
import React from 'react';
import { Text, View } from 'react-native';
import useBluetoothDevices, { useManager, useManagerState } from './useBluetoothDevices';
export default function App() {
const bleManager = useManager();
const state = useManagerState(bleManager);
console.log('Info:', state);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'blue'}}>
<Text style={{fontSize: 18, color: 'white'}}>State: {state}</Text>
{state === 'PoweredOn' && <DeviceScanner bleManager={bleManager} />}
</View>
);
}
function DeviceScanner({ bleManager }) {
const [devices] = useBluetoothDevices(bleManager);
React.useEffect(() => {
console.log(devices);
}, [devices]);
return (
<View>
{devices.filter(({name}) => name).map((device, index) => (<Text key={`-${index}`} style={{fontSize: 14, color: 'white'}}>{device.name}</Text>))}
</View>
)
}
@@ -0,0 +1,70 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { BleManager, State, Device } from "react-native-ble-plx";
import { uniqBy } from "lodash";
export function useManager() {
return useMemo(() => new BleManager(), []);
}
export function useManagerState(bleManager: BleManager): State | null {
const [state, setState] = useState<State | null>(null);
const isMounted = useMounted();
useEffect(() => {
if (!bleManager) return;
bleManager.onStateChange((state) => {
if (isMounted.current) {
setState(state);
}
}, true);
}, [bleManager]);
return state;
}
function useMounted() {
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
}
export function useBluetoothDevices(
bleManager: BleManager
): [Device[], null | string] {
const isMoutned = useMounted();
const [error, setError] = useState<string | null>(null);
const [devices, setDevices] = useState<Device[]>([]);
useEffect(() => {
bleManager.startDeviceScan(
[],
{ allowDuplicates: false },
(e, scannedDevice) => {
if (!isMoutned.current) return;
if (e) {
setError(e.message);
}
if (!scannedDevice) return;
setDevices((oldDevices) =>
uniqBy([...oldDevices, scannedDevice], "id")
);
}
);
return () => {
bleManager.stopDeviceScan();
};
}, [bleManager]);
return [devices, error];
}
export default useBluetoothDevices;
File renamed without changes.
+80
View File
@@ -0,0 +1,80 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
/artifacts
/scripts/start.command
/ios
/android
# @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8
# The following patterns were generated by expo-cli
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Expo
.expo/
web-build/
dist/
# @end expo-cli
Whitespace-only changes.
+3 -3
View File
@@ -1,7 +1,7 @@
const path = require('path');
const path = require("path");
const folderName = path.basename(__dirname);
const cleanName = folderName.replace(/[_\s-]/g, '');
const appId = 'dev.bacon.' + cleanName;
const cleanName = folderName.replace(/[_\s-]/g, "");
const appId = "dev.bacon." + cleanName;
module.exports = ({ config }) => {
if (!config.extra) config.extra = {};
+15 -10
View File
@@ -1,17 +1,22 @@
{
"expo": {
"name": "branch",
"icon": "https://github.com/expo.png",
"splash": {
"image": "https://github.com/expo.png"
},
"plugins": [
[
"@config-plugins/react-native-branch",
{
"icon": "https://icogen.vercel.app/api/icon?icon=1f334",
"ios": {
"config": {
"branch": {
"apiKey": "key_live_f9f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8"
}
]
}
},
"android": {
"config": {
"branch": {
"apiKey": "key_live_f9f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8"
}
}
},
"plugins": [
"@config-plugins/react-native-branch"
]
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
+2 -2
View File
@@ -1,5 +1,5 @@
import { registerRootComponent } from 'expo';
import { registerRootComponent } from "expo";
import App from './src/App';
import App from "./src/App";
registerRootComponent(App);
+6
View File
@@ -0,0 +1,6 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("@expo/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = config;
+15 -9
View File
@@ -1,19 +1,25 @@
{
"name": "@config-plugins-app/react-native-branch",
"version": "1.0.0",
"private": true,
"main": "./index.js",
"version": "1.0.0",
"scripts": {
"start": "expo start --dev-client",
"ios": "expo run:ios",
"android": "expo run:android"
},
"dependencies": {
"@config-plugins/react-native-branch": "workspace:*",
"expo": "~56",
"expo-splash-screen": "~56.0.10",
"react": "19.2.3",
"react-native": "0.85.3",
"react-native-branch": "^6.10.0"
}
"@config-plugins/react-native-branch": "*",
"expo": "^45.0.0",
"expo-splash-screen": "~0.15.1",
"react": "17.0.2",
"react-native": "0.68.2",
"react-native-branch": "^5.4.0",
"expo-status-bar": "~1.3.0",
"react-dom": "17.0.2",
"react-native-web": "0.17.7"
},
"devDependencies": {
"@babel/core": "^7.12.9"
},
"private": true
}
+3 -2
View File
@@ -1,8 +1,9 @@
import { Text, View } from 'react-native';
import React from "react";
import { Text, View } from "react-native";
export default function App() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Branch</Text>
</View>
);
Loaded 100 of 481 files, more files were not shown because too many files have changed in this diff. Show more