├── .circleci └── config.yml ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .husky ├── .npmignore ├── commit-msg └── pre-commit ├── .yarnrc ├── CONTRIBUTING.md ├── LICENSE ├── README-zh_CN.md ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── reactnativekit │ ├── KitModule.java │ └── KitPackage.java ├── babel.config.js ├── example ├── .buckconfig ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── __tests__ │ └── App-test.tsx ├── _bundle │ └── config ├── _ruby-version ├── android │ ├── app │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── toolkitexample │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── toolkitexample │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MainApplication.java │ │ │ │ └── newarchitecture │ │ │ │ ├── MainApplicationReactNativeHost.java │ │ │ │ ├── components │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ └── modules │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ ├── jni │ │ │ ├── Android.mk │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ ├── MainApplicationModuleProvider.h │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ ├── MainComponentsRegistry.cpp │ │ │ ├── MainComponentsRegistry.h │ │ │ └── OnLoad.cpp │ │ │ └── res │ │ │ ├── drawable │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── Podfile.lock │ ├── ToolkitExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── ToolkitExample.xcscheme │ ├── ToolkitExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── ToolkitExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ └── ToolkitExampleTests │ │ ├── Info.plist │ │ └── ToolkitExampleTests.m ├── metro.config.js ├── package.json ├── src │ └── App.tsx ├── tsconfig.json └── yarn.lock ├── ios ├── MBProgressHUD │ ├── .gitignore │ ├── .travis.yml │ ├── CHANGELOG.mdown │ ├── CONTRIBUTING.md │ ├── Framework-Info.plist │ ├── LICENSE │ ├── MBProgressHUD-Prefix.pch │ ├── MBProgressHUD.h │ ├── MBProgressHUD.m │ ├── MBProgressHUD.podspec │ ├── MBProgressHUD.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── MBProgressHUD Framework tvOS.xcscheme │ │ │ ├── MBProgressHUD Framework.xcscheme │ │ │ └── MBProgressHUD.xcscheme │ ├── MBProgressHUD.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── README.mdown │ └── include │ │ ├── MBProgressHUD │ │ └── MBProgressHUD.h │ │ └── module.modulemap ├── RCTConvert+RNToolkit.h ├── RCTConvert+RNToolkit.m ├── RNToolkit.h ├── RNToolkit.m ├── RNToolkit.xcodeproj │ └── project.pbxproj ├── RTKAppearance.h ├── RTKAppearance.m ├── RTKDocumentCamera.h ├── RTKDocumentCamera.m ├── RTKMediaLibrary.h ├── RTKMediaLibrary.m ├── RTKQuickLookView │ ├── RTKQuickLookManager.h │ ├── RTKQuickLookManager.m │ ├── RTKQuickLookView.h │ └── RTKQuickLookView.m ├── RTKThumbnailGenerator.h ├── RTKThumbnailGenerator.m ├── RTKVideoEditor.h └── RTKVideoEditor.m ├── package.json ├── react-native-app-toolkit.podspec ├── scripts └── bootstrap.js ├── src ├── __tests__ │ └── index.test.tsx ├── index.ts ├── internal │ └── nativeInterface.ts ├── packages │ ├── Appearance.tsx │ ├── DocumentCamera.tsx │ ├── QuickLook.tsx │ ├── ThumbnailGenerator.tsx │ ├── VideoEditor.tsx │ └── VideoThumbnail.tsx └── types.d.ts ├── tsconfig.build.json ├── tsconfig.json ├── website ├── .gitignore ├── README.md ├── babel.config.js ├── blog │ ├── 2019-05-28-first-blog-post.md │ ├── 2019-05-29-long-blog-post.md │ ├── 2021-08-01-mdx-blog-post.mdx │ ├── 2021-08-26-welcome │ │ ├── docusaurus-plushie-banner.jpeg │ │ └── index.md │ └── authors.yml ├── docs │ ├── api │ │ ├── _category_.json │ │ ├── appearance.md │ │ ├── document-camera.md │ │ ├── quick-look.md │ │ ├── thumbnail-generator.md │ │ ├── video-editor.md │ │ └── video-thumbnail.md │ ├── getting-started.md │ ├── troubleshooting.md │ └── usage.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.module.css │ │ ├── index.tsx │ │ └── markdown-page.md ├── static │ ├── .nojekyll │ ├── img │ │ ├── docusaurus.png │ │ ├── favicon.ico │ │ ├── logo.svg │ │ ├── tutorial │ │ │ ├── docsVersionDropdown.png │ │ │ └── localeDropdown.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg │ └── screenshot │ │ └── IMG_2589.PNG ├── tsconfig.json └── yarn.lock └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | executors: 4 | default: 5 | docker: 6 | - image: circleci/node:10 7 | working_directory: ~/project 8 | 9 | commands: 10 | attach_project: 11 | steps: 12 | - attach_workspace: 13 | at: ~/project 14 | 15 | jobs: 16 | install-dependencies: 17 | executor: default 18 | steps: 19 | - checkout 20 | - attach_project 21 | - restore_cache: 22 | keys: 23 | - dependencies-{{ checksum "package.json" }} 24 | - dependencies- 25 | - restore_cache: 26 | keys: 27 | - dependencies-example-{{ checksum "example/package.json" }} 28 | - dependencies-example- 29 | - run: 30 | name: Install dependencies 31 | command: | 32 | yarn install --cwd example --frozen-lockfile 33 | yarn install --frozen-lockfile 34 | - save_cache: 35 | key: dependencies-{{ checksum "package.json" }} 36 | paths: node_modules 37 | - save_cache: 38 | key: dependencies-example-{{ checksum "example/package.json" }} 39 | paths: example/node_modules 40 | - persist_to_workspace: 41 | root: . 42 | paths: . 43 | 44 | lint: 45 | executor: default 46 | steps: 47 | - attach_project 48 | - run: 49 | name: Lint files 50 | command: | 51 | yarn lint 52 | 53 | typescript: 54 | executor: default 55 | steps: 56 | - attach_project 57 | - run: 58 | name: Typecheck files 59 | command: | 60 | yarn typescript 61 | 62 | unit-tests: 63 | executor: default 64 | steps: 65 | - attach_project 66 | - run: 67 | name: Run unit tests 68 | command: | 69 | yarn test --coverage 70 | - store_artifacts: 71 | path: coverage 72 | destination: coverage 73 | 74 | build-package: 75 | executor: default 76 | steps: 77 | - attach_project 78 | - run: 79 | name: Build package 80 | command: | 81 | yarn prepare 82 | 83 | workflows: 84 | build-and-test: 85 | jobs: 86 | - install-dependencies 87 | - lint: 88 | requires: 89 | - install-dependencies 90 | - typescript: 91 | requires: 92 | - install-dependencies 93 | - unit-tests: 94 | requires: 95 | - install-dependencies 96 | - build-package: 97 | requires: 98 | - install-dependencies 99 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .classpath 35 | .cxx 36 | .gradle 37 | .idea 38 | .project 39 | .settings 40 | local.properties 41 | android.iml 42 | 43 | # Cocoapods 44 | # 45 | example/ios/Pods 46 | 47 | # node.js 48 | # 49 | node_modules/ 50 | npm-debug.log 51 | yarn-debug.log 52 | yarn-error.log 53 | 54 | # BUCK 55 | buck-out/ 56 | \.buckd/ 57 | android/app/libs 58 | android/keystores/debug.keystore 59 | 60 | # Expo 61 | .expo/* 62 | 63 | # generated by bob 64 | lib/ 65 | -------------------------------------------------------------------------------- /.husky/.npmignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint -E HUSKY_GIT_PARAMS 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint && yarn typescript 5 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # Override Yarn command so we can automatically setup the repo on running `yarn` 2 | 3 | yarn-path "scripts/bootstrap.js" 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 luoxuhai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-zh_CN.md: -------------------------------------------------------------------------------- 1 |
2 |

⚡️ + 📱 React Native App Toolkit

3 |

一个高质量的 react-native 工具库。

4 |
5 | 6 | [English](https://github.com/luoxuhai/react-native-app-toolkit#%EF%B8%8F---react-native-app-toolkit) | 简体中文 7 | 8 | 🚧 当前只支持 iOS 平台 🚧 9 | 10 | ## 入门 11 | 12 | 如果你正在使用 `react-native >= 0.60` 你只需要做一个简单的: 13 | 14 | ```shell 15 | yarn add react-native-app-toolkit 16 | ``` 17 | 18 | 如果使用 npm: 19 | 20 | ```shell 21 | npm i react-native-app-toolkit --save 22 | ``` 23 | 24 | 之后,我们需要安装依赖项才能在 iOS 上使用该项目(如果您在 Android 上使用,则可以跳过此部分)。 25 | 26 | 现在运行一个简单的: `npx pod-install` 或 `cd ios && pod install`. 之后,您应该能够在平台、iOS 和 Android 上使用该库。 27 | 28 | ## 文档 29 | 30 | - [入门](https://luoxuhai.github.io/react-native-app-toolkit/docs/getting-started) 31 | - [API 参考](https://luoxuhai.github.io/react-native-app-toolkit/docs/api/appearance) 32 | 33 | ## 社区 34 | 35 | - [Discussions](https://github.com/luoxuhai/react-native-app-toolkit/discussions) 36 | 37 | ## 贡献 38 | 39 | 请参阅 [贡献指南](CONTRIBUTING.md) 以了解如何为存储库和开发工作流程做出贡献。 40 | 41 | ## 开源协议 42 | 43 | [MIT](/LICENSE) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

⚡️ + 📱 React Native App Toolkit

3 |

High-quality toolkit for React Native using native code.

4 |
5 | 6 | English | [简体中文](./README-zh_CN.md) 7 | 8 | 🚧 Currently only supports iOS 🚧 9 | 10 | ## Installation 11 | 12 | If you are using `react-native >= 0.60` you just need to do a simple: 13 | 14 | ```shell 15 | yarn add react-native-app-toolkit 16 | ``` 17 | 18 | Or if are using npm: 19 | 20 | ```shell 21 | npm i react-native-app-toolkit --save 22 | ``` 23 | 24 | After that, we need to install the dependencies to use the project on iOS(you can skip this part, if you are using this on Android). 25 | 26 | Now run a simple: `npx pod-install` or `cd ios && pod install`. After that, you should be able to use the library on both Platforms, iOS and Android. 27 | 28 | ## Documentation 29 | 30 | - [Getting Started](https://luoxuhai.github.io/react-native-app-toolkit/docs/getting-started) 31 | - [API Reference](https://luoxuhai.github.io/react-native-app-toolkit/docs/api/appearance) 32 | 33 | ## Community 34 | 35 | - [Discussions](https://github.com/luoxuhai/react-native-app-toolkit/discussions) 36 | 37 | ## Contributing 38 | 39 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. 40 | 41 | ## License 42 | 43 | [MIT](/LICENSE) 44 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | if (project == rootProject) { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | jcenter() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.3' 11 | } 12 | } 13 | } 14 | 15 | apply plugin: 'com.android.library' 16 | 17 | def safeExtGet(prop, fallback) { 18 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 19 | } 20 | 21 | android { 22 | compileSdkVersion safeExtGet('Kit_compileSdkVersion', 29) 23 | defaultConfig { 24 | minSdkVersion safeExtGet('Kit_minSdkVersion', 16) 25 | targetSdkVersion safeExtGet('Kit_targetSdkVersion', 29) 26 | versionCode 1 27 | versionName "1.0" 28 | 29 | } 30 | 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | } 35 | } 36 | lintOptions { 37 | disable 'GradleCompatible' 38 | } 39 | compileOptions { 40 | sourceCompatibility JavaVersion.VERSION_1_8 41 | targetCompatibility JavaVersion.VERSION_1_8 42 | } 43 | } 44 | 45 | repositories { 46 | mavenLocal() 47 | maven { 48 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 49 | url("$rootDir/../node_modules/react-native/android") 50 | } 51 | google() 52 | mavenCentral() 53 | jcenter() 54 | } 55 | 56 | dependencies { 57 | //noinspection GradleDynamicVersion 58 | implementation "com.facebook.react:react-native:+" // From node_modules 59 | } 60 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativekit/KitModule.java: -------------------------------------------------------------------------------- 1 | package com.reactnativekit; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.facebook.react.bridge.Promise; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 8 | import com.facebook.react.bridge.ReactMethod; 9 | import com.facebook.react.module.annotations.ReactModule; 10 | 11 | @ReactModule(name = KitModule.NAME) 12 | public class KitModule extends ReactContextBaseJavaModule { 13 | public static final String NAME = "Kit"; 14 | 15 | public KitModule(ReactApplicationContext reactContext) { 16 | super(reactContext); 17 | } 18 | 19 | @Override 20 | @NonNull 21 | public String getName() { 22 | return NAME; 23 | } 24 | 25 | 26 | // Example method 27 | // See https://reactnative.dev/docs/native-modules-android 28 | @ReactMethod 29 | public void multiply(int a, int b, Promise promise) { 30 | promise.resolve(a * b); 31 | } 32 | 33 | public static native int nativeMultiply(int a, int b); 34 | } 35 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativekit/KitPackage.java: -------------------------------------------------------------------------------- 1 | package com.reactnativekit; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class KitPackage implements ReactPackage { 15 | @NonNull 16 | @Override 17 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 18 | List modules = new ArrayList<>(); 19 | modules.add(new KitModule(reactContext)); 20 | return modules; 21 | } 22 | 23 | @NonNull 24 | @Override 25 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 26 | return Collections.emptyList(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | parser: '@typescript-eslint/parser', 5 | plugins: ['@typescript-eslint'], 6 | overrides: [ 7 | { 8 | files: ['*.ts', '*.tsx'], 9 | rules: { 10 | '@typescript-eslint/no-shadow': ['error'], 11 | 'no-shadow': 'off', 12 | 'no-undef': 'off', 13 | }, 14 | }, 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | *.hprof 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # Ruby / CocoaPods 60 | /ios/Pods/ 61 | /vendor/bundle/ 62 | -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby '2.7.4' 5 | 6 | gem 'cocoapods', '~> 1.11', '>= 1.11.2' 7 | -------------------------------------------------------------------------------- /example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.5) 5 | rexml 6 | activesupport (6.1.5) 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | i18n (>= 1.6, < 2) 9 | minitest (>= 5.1) 10 | tzinfo (~> 2.0) 11 | zeitwerk (~> 2.3) 12 | addressable (2.8.0) 13 | public_suffix (>= 2.0.2, < 5.0) 14 | algoliasearch (1.27.5) 15 | httpclient (~> 2.8, >= 2.8.3) 16 | json (>= 1.5.1) 17 | atomos (0.1.3) 18 | claide (1.1.0) 19 | cocoapods (1.11.3) 20 | addressable (~> 2.8) 21 | claide (>= 1.0.2, < 2.0) 22 | cocoapods-core (= 1.11.3) 23 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 24 | cocoapods-downloader (>= 1.4.0, < 2.0) 25 | cocoapods-plugins (>= 1.0.0, < 2.0) 26 | cocoapods-search (>= 1.0.0, < 2.0) 27 | cocoapods-trunk (>= 1.4.0, < 2.0) 28 | cocoapods-try (>= 1.1.0, < 2.0) 29 | colored2 (~> 3.1) 30 | escape (~> 0.0.4) 31 | fourflusher (>= 2.3.0, < 3.0) 32 | gh_inspector (~> 1.0) 33 | molinillo (~> 0.8.0) 34 | nap (~> 1.0) 35 | ruby-macho (>= 1.0, < 3.0) 36 | xcodeproj (>= 1.21.0, < 2.0) 37 | cocoapods-core (1.11.3) 38 | activesupport (>= 5.0, < 7) 39 | addressable (~> 2.8) 40 | algoliasearch (~> 1.0) 41 | concurrent-ruby (~> 1.1) 42 | fuzzy_match (~> 2.0.4) 43 | nap (~> 1.0) 44 | netrc (~> 0.11) 45 | public_suffix (~> 4.0) 46 | typhoeus (~> 1.0) 47 | cocoapods-deintegrate (1.0.5) 48 | cocoapods-downloader (1.6.3) 49 | cocoapods-plugins (1.0.0) 50 | nap 51 | cocoapods-search (1.0.1) 52 | cocoapods-trunk (1.6.0) 53 | nap (>= 0.8, < 2.0) 54 | netrc (~> 0.11) 55 | cocoapods-try (1.2.0) 56 | colored2 (3.1.2) 57 | concurrent-ruby (1.1.10) 58 | escape (0.0.4) 59 | ethon (0.15.0) 60 | ffi (>= 1.15.0) 61 | ffi (1.15.5) 62 | fourflusher (2.3.1) 63 | fuzzy_match (2.0.4) 64 | gh_inspector (1.1.3) 65 | httpclient (2.8.3) 66 | i18n (1.10.0) 67 | concurrent-ruby (~> 1.0) 68 | json (2.6.1) 69 | minitest (5.15.0) 70 | molinillo (0.8.0) 71 | nanaimo (0.3.0) 72 | nap (1.1.0) 73 | netrc (0.11.0) 74 | public_suffix (4.0.7) 75 | rexml (3.2.5) 76 | ruby-macho (2.5.1) 77 | typhoeus (1.4.0) 78 | ethon (>= 0.9.0) 79 | tzinfo (2.0.4) 80 | concurrent-ruby (~> 1.0) 81 | xcodeproj (1.21.0) 82 | CFPropertyList (>= 2.3.3, < 4.0) 83 | atomos (~> 0.1.3) 84 | claide (>= 1.0.2, < 2.0) 85 | colored2 (~> 3.1) 86 | nanaimo (~> 0.3.0) 87 | rexml (~> 3.2.4) 88 | zeitwerk (2.5.4) 89 | 90 | PLATFORMS 91 | ruby 92 | 93 | DEPENDENCIES 94 | cocoapods (~> 1.11, >= 1.11.2) 95 | 96 | RUBY VERSION 97 | ruby 2.7.4p191 98 | 99 | BUNDLED WITH 100 | 2.2.27 101 | -------------------------------------------------------------------------------- /example/__tests__/App-test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../src/App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /example/_bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /example/_ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.4 2 | -------------------------------------------------------------------------------- /example/android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.toolkitexample", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.toolkitexample", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/toolkitexample/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.toolkitexample; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 22 | import com.facebook.react.ReactInstanceEventListener; 23 | import com.facebook.react.ReactInstanceManager; 24 | import com.facebook.react.bridge.ReactContext; 25 | import com.facebook.react.modules.network.NetworkingModule; 26 | import okhttp3.OkHttpClient; 27 | 28 | public class ReactNativeFlipper { 29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 30 | if (FlipperUtils.shouldEnableFlipper(context)) { 31 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 32 | 33 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 34 | client.addPlugin(new ReactFlipperPlugin()); 35 | client.addPlugin(new DatabasesFlipperPlugin(context)); 36 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 37 | client.addPlugin(CrashReporterPlugin.getInstance()); 38 | 39 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 40 | NetworkingModule.setCustomClientBuilder( 41 | new NetworkingModule.CustomClientBuilder() { 42 | @Override 43 | public void apply(OkHttpClient.Builder builder) { 44 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 45 | } 46 | }); 47 | client.addPlugin(networkFlipperPlugin); 48 | client.start(); 49 | 50 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 51 | // Hence we run if after all native modules have been initialized 52 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 53 | if (reactContext == null) { 54 | reactInstanceManager.addReactInstanceEventListener( 55 | new ReactInstanceEventListener() { 56 | @Override 57 | public void onReactContextInitialized(ReactContext reactContext) { 58 | reactInstanceManager.removeReactInstanceEventListener(this); 59 | reactContext.runOnNativeModulesQueueThread( 60 | new Runnable() { 61 | @Override 62 | public void run() { 63 | client.addPlugin(new FrescoFlipperPlugin()); 64 | } 65 | }); 66 | } 67 | }); 68 | } else { 69 | client.addPlugin(new FrescoFlipperPlugin()); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/toolkitexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.toolkitexample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.ReactRootView; 6 | 7 | public class MainActivity extends ReactActivity { 8 | 9 | /** 10 | * Returns the name of the main component registered from JavaScript. This is used to schedule 11 | * rendering of the component. 12 | */ 13 | @Override 14 | protected String getMainComponentName() { 15 | return "ToolkitExample"; 16 | } 17 | 18 | /** 19 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and 20 | * you can specify the rendered you wish to use (Fabric or the older renderer). 21 | */ 22 | @Override 23 | protected ReactActivityDelegate createReactActivityDelegate() { 24 | return new MainActivityDelegate(this, getMainComponentName()); 25 | } 26 | 27 | public static class MainActivityDelegate extends ReactActivityDelegate { 28 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) { 29 | super(activity, mainComponentName); 30 | } 31 | 32 | @Override 33 | protected ReactRootView createRootView() { 34 | ReactRootView reactRootView = new ReactRootView(getContext()); 35 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 36 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED); 37 | return reactRootView; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/toolkitexample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.toolkitexample; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.react.config.ReactFeatureFlags; 11 | import com.facebook.soloader.SoLoader; 12 | import com.toolkitexample.newarchitecture.MainApplicationReactNativeHost; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.util.List; 15 | 16 | public class MainApplication extends Application implements ReactApplication { 17 | 18 | private final ReactNativeHost mReactNativeHost = 19 | new ReactNativeHost(this) { 20 | @Override 21 | public boolean getUseDeveloperSupport() { 22 | return BuildConfig.DEBUG; 23 | } 24 | 25 | @Override 26 | protected List getPackages() { 27 | @SuppressWarnings("UnnecessaryLocalVariable") 28 | List packages = new PackageList(this).getPackages(); 29 | // Packages that cannot be autolinked yet can be added manually here, for example: 30 | // packages.add(new MyReactNativePackage()); 31 | return packages; 32 | } 33 | 34 | @Override 35 | protected String getJSMainModuleName() { 36 | return "index"; 37 | } 38 | }; 39 | 40 | private final ReactNativeHost mNewArchitectureNativeHost = 41 | new MainApplicationReactNativeHost(this); 42 | 43 | @Override 44 | public ReactNativeHost getReactNativeHost() { 45 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 46 | return mNewArchitectureNativeHost; 47 | } else { 48 | return mReactNativeHost; 49 | } 50 | } 51 | 52 | @Override 53 | public void onCreate() { 54 | super.onCreate(); 55 | // If you opted-in for the New Architecture, we enable the TurboModule system 56 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 57 | SoLoader.init(this, /* native exopackage */ false); 58 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 59 | } 60 | 61 | /** 62 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 63 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 64 | * 65 | * @param context 66 | * @param reactInstanceManager 67 | */ 68 | private static void initializeFlipper( 69 | Context context, ReactInstanceManager reactInstanceManager) { 70 | if (BuildConfig.DEBUG) { 71 | try { 72 | /* 73 | We use reflection here to pick up the class that initializes Flipper, 74 | since Flipper library is not available in release mode 75 | */ 76 | Class aClass = Class.forName("com.toolkitexample.ReactNativeFlipper"); 77 | aClass 78 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 79 | .invoke(null, context, reactInstanceManager); 80 | } catch (ClassNotFoundException e) { 81 | e.printStackTrace(); 82 | } catch (NoSuchMethodException e) { 83 | e.printStackTrace(); 84 | } catch (IllegalAccessException e) { 85 | e.printStackTrace(); 86 | } catch (InvocationTargetException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/toolkitexample/newarchitecture/MainApplicationReactNativeHost.java: -------------------------------------------------------------------------------- 1 | package com.toolkitexample.newarchitecture; 2 | 3 | import android.app.Application; 4 | import androidx.annotation.NonNull; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactInstanceManager; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate; 10 | import com.facebook.react.bridge.JSIModulePackage; 11 | import com.facebook.react.bridge.JSIModuleProvider; 12 | import com.facebook.react.bridge.JSIModuleSpec; 13 | import com.facebook.react.bridge.JSIModuleType; 14 | import com.facebook.react.bridge.JavaScriptContextHolder; 15 | import com.facebook.react.bridge.ReactApplicationContext; 16 | import com.facebook.react.bridge.UIManager; 17 | import com.facebook.react.fabric.ComponentFactory; 18 | import com.facebook.react.fabric.CoreComponentsRegistry; 19 | import com.facebook.react.fabric.EmptyReactNativeConfig; 20 | import com.facebook.react.fabric.FabricJSIModuleProvider; 21 | import com.facebook.react.uimanager.ViewManagerRegistry; 22 | import com.toolkitexample.BuildConfig; 23 | import com.toolkitexample.newarchitecture.components.MainComponentsRegistry; 24 | import com.toolkitexample.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | /** 29 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both 30 | * TurboModule delegates and the Fabric Renderer. 31 | * 32 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 33 | * `newArchEnabled` property). Is ignored otherwise. 34 | */ 35 | public class MainApplicationReactNativeHost extends ReactNativeHost { 36 | public MainApplicationReactNativeHost(Application application) { 37 | super(application); 38 | } 39 | 40 | @Override 41 | public boolean getUseDeveloperSupport() { 42 | return BuildConfig.DEBUG; 43 | } 44 | 45 | @Override 46 | protected List getPackages() { 47 | List packages = new PackageList(this).getPackages(); 48 | // Packages that cannot be autolinked yet can be added manually here, for example: 49 | // packages.add(new MyReactNativePackage()); 50 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: 51 | // packages.add(new TurboReactPackage() { ... }); 52 | // If you have custom Fabric Components, their ViewManagers should also be loaded here 53 | // inside a ReactPackage. 54 | return packages; 55 | } 56 | 57 | @Override 58 | protected String getJSMainModuleName() { 59 | return "index"; 60 | } 61 | 62 | @NonNull 63 | @Override 64 | protected ReactPackageTurboModuleManagerDelegate.Builder 65 | getReactPackageTurboModuleManagerDelegateBuilder() { 66 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary 67 | // for the new architecture and to use TurboModules correctly. 68 | return new MainApplicationTurboModuleManagerDelegate.Builder(); 69 | } 70 | 71 | @Override 72 | protected JSIModulePackage getJSIModulePackage() { 73 | return new JSIModulePackage() { 74 | @Override 75 | public List getJSIModules( 76 | final ReactApplicationContext reactApplicationContext, 77 | final JavaScriptContextHolder jsContext) { 78 | final List specs = new ArrayList<>(); 79 | 80 | // Here we provide a new JSIModuleSpec that will be responsible of providing the 81 | // custom Fabric Components. 82 | specs.add( 83 | new JSIModuleSpec() { 84 | @Override 85 | public JSIModuleType getJSIModuleType() { 86 | return JSIModuleType.UIManager; 87 | } 88 | 89 | @Override 90 | public JSIModuleProvider getJSIModuleProvider() { 91 | final ComponentFactory componentFactory = new ComponentFactory(); 92 | CoreComponentsRegistry.register(componentFactory); 93 | 94 | // Here we register a Components Registry. 95 | // The one that is generated with the template contains no components 96 | // and just provides you the one from React Native core. 97 | MainComponentsRegistry.register(componentFactory); 98 | 99 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); 100 | 101 | ViewManagerRegistry viewManagerRegistry = 102 | new ViewManagerRegistry( 103 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); 104 | 105 | return new FabricJSIModuleProvider( 106 | reactApplicationContext, 107 | componentFactory, 108 | new EmptyReactNativeConfig(), 109 | viewManagerRegistry); 110 | } 111 | }); 112 | return specs; 113 | } 114 | }; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/toolkitexample/newarchitecture/components/MainComponentsRegistry.java: -------------------------------------------------------------------------------- 1 | package com.toolkitexample.newarchitecture.components; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.proguard.annotations.DoNotStrip; 5 | import com.facebook.react.fabric.ComponentFactory; 6 | import com.facebook.soloader.SoLoader; 7 | 8 | /** 9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a 10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 11 | * folder for you). 12 | * 13 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 14 | * `newArchEnabled` property). Is ignored otherwise. 15 | */ 16 | @DoNotStrip 17 | public class MainComponentsRegistry { 18 | static { 19 | SoLoader.loadLibrary("fabricjni"); 20 | } 21 | 22 | @DoNotStrip private final HybridData mHybridData; 23 | 24 | @DoNotStrip 25 | private native HybridData initHybrid(ComponentFactory componentFactory); 26 | 27 | @DoNotStrip 28 | private MainComponentsRegistry(ComponentFactory componentFactory) { 29 | mHybridData = initHybrid(componentFactory); 30 | } 31 | 32 | @DoNotStrip 33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) { 34 | return new MainComponentsRegistry(componentFactory); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/toolkitexample/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java: -------------------------------------------------------------------------------- 1 | package com.toolkitexample.newarchitecture.modules; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.soloader.SoLoader; 8 | import java.util.List; 9 | 10 | /** 11 | * Class responsible to load the TurboModules. This class has native methods and needs a 12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 13 | * folder for you). 14 | * 15 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 16 | * `newArchEnabled` property). Is ignored otherwise. 17 | */ 18 | public class MainApplicationTurboModuleManagerDelegate 19 | extends ReactPackageTurboModuleManagerDelegate { 20 | 21 | private static volatile boolean sIsSoLibraryLoaded; 22 | 23 | protected MainApplicationTurboModuleManagerDelegate( 24 | ReactApplicationContext reactApplicationContext, List packages) { 25 | super(reactApplicationContext, packages); 26 | } 27 | 28 | protected native HybridData initHybrid(); 29 | 30 | native boolean canCreateTurboModule(String moduleName); 31 | 32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { 33 | protected MainApplicationTurboModuleManagerDelegate build( 34 | ReactApplicationContext context, List packages) { 35 | return new MainApplicationTurboModuleManagerDelegate(context, packages); 36 | } 37 | } 38 | 39 | @Override 40 | protected synchronized void maybeLoadOtherSoLibraries() { 41 | if (!sIsSoLibraryLoaded) { 42 | // If you change the name of your application .so file in the Android.mk file, 43 | // make sure you update the name here as well. 44 | SoLoader.loadLibrary("toolkitexample_appmodules"); 45 | sIsSoLibraryLoaded = true; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | THIS_DIR := $(call my-dir) 2 | 3 | include $(REACT_ANDROID_DIR)/Android-prebuilt.mk 4 | 5 | # If you wish to add a custom TurboModule or Fabric component in your app you 6 | # will have to include the following autogenerated makefile. 7 | # include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk 8 | include $(CLEAR_VARS) 9 | 10 | LOCAL_PATH := $(THIS_DIR) 11 | 12 | # You can customize the name of your application .so file here. 13 | LOCAL_MODULE := toolkitexample_appmodules 14 | 15 | LOCAL_C_INCLUDES := $(LOCAL_PATH) 16 | LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) 17 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) 18 | 19 | # If you wish to add a custom TurboModule or Fabric component in your app you 20 | # will have to uncomment those lines to include the generated source 21 | # files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni) 22 | # 23 | # LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni 24 | # LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) 25 | # LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni 26 | 27 | # Here you should add any native library you wish to depend on. 28 | LOCAL_SHARED_LIBRARIES := \ 29 | libfabricjni \ 30 | libfbjni \ 31 | libfolly_futures \ 32 | libfolly_json \ 33 | libglog \ 34 | libjsi \ 35 | libreact_codegen_rncore \ 36 | libreact_debug \ 37 | libreact_nativemodule_core \ 38 | libreact_render_componentregistry \ 39 | libreact_render_core \ 40 | libreact_render_debug \ 41 | libreact_render_graphics \ 42 | librrc_view \ 43 | libruntimeexecutor \ 44 | libturbomodulejsijni \ 45 | libyoga 46 | 47 | LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall 48 | 49 | include $(BUILD_SHARED_LIBRARY) 50 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationModuleProvider.h" 2 | 3 | #include 4 | 5 | namespace facebook { 6 | namespace react { 7 | 8 | std::shared_ptr MainApplicationModuleProvider( 9 | const std::string moduleName, 10 | const JavaTurboModule::InitParams ¶ms) { 11 | // Here you can provide your own module provider for TurboModules coming from 12 | // either your application or from external libraries. The approach to follow 13 | // is similar to the following (for a library called `samplelibrary`: 14 | // 15 | // auto module = samplelibrary_ModuleProvider(moduleName, params); 16 | // if (module != nullptr) { 17 | // return module; 18 | // } 19 | // return rncore_ModuleProvider(moduleName, params); 20 | return rncore_ModuleProvider(moduleName, params); 21 | } 22 | 23 | } // namespace react 24 | } // namespace facebook 25 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | std::shared_ptr MainApplicationModuleProvider( 12 | const std::string moduleName, 13 | const JavaTurboModule::InitParams ¶ms); 14 | 15 | } // namespace react 16 | } // namespace facebook 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationTurboModuleManagerDelegate.h" 2 | #include "MainApplicationModuleProvider.h" 3 | 4 | namespace facebook { 5 | namespace react { 6 | 7 | jni::local_ref 8 | MainApplicationTurboModuleManagerDelegate::initHybrid( 9 | jni::alias_ref) { 10 | return makeCxxInstance(); 11 | } 12 | 13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() { 14 | registerHybrid({ 15 | makeNativeMethod( 16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), 17 | makeNativeMethod( 18 | "canCreateTurboModule", 19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), 20 | }); 21 | } 22 | 23 | std::shared_ptr 24 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 25 | const std::string name, 26 | const std::shared_ptr jsInvoker) { 27 | // Not implemented yet: provide pure-C++ NativeModules here. 28 | return nullptr; 29 | } 30 | 31 | std::shared_ptr 32 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 33 | const std::string name, 34 | const JavaTurboModule::InitParams ¶ms) { 35 | return MainApplicationModuleProvider(name, params); 36 | } 37 | 38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( 39 | std::string name) { 40 | return getTurboModule(name, nullptr) != nullptr || 41 | getTurboModule(name, {.moduleName = name}) != nullptr; 42 | } 43 | 44 | } // namespace react 45 | } // namespace facebook 46 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace facebook { 8 | namespace react { 9 | 10 | class MainApplicationTurboModuleManagerDelegate 11 | : public jni::HybridClass< 12 | MainApplicationTurboModuleManagerDelegate, 13 | TurboModuleManagerDelegate> { 14 | public: 15 | // Adapt it to the package you used for your Java class. 16 | static constexpr auto kJavaDescriptor = 17 | "Lcom/toolkitexample/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; 18 | 19 | static jni::local_ref initHybrid(jni::alias_ref); 20 | 21 | static void registerNatives(); 22 | 23 | std::shared_ptr getTurboModule( 24 | const std::string name, 25 | const std::shared_ptr jsInvoker) override; 26 | std::shared_ptr getTurboModule( 27 | const std::string name, 28 | const JavaTurboModule::InitParams ¶ms) override; 29 | 30 | /** 31 | * Test-only method. Allows user to verify whether a TurboModule can be 32 | * created by instances of this class. 33 | */ 34 | bool canCreateTurboModule(std::string name); 35 | }; 36 | 37 | } // namespace react 38 | } // namespace facebook 39 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainComponentsRegistry.cpp: -------------------------------------------------------------------------------- 1 | #include "MainComponentsRegistry.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} 12 | 13 | std::shared_ptr 14 | MainComponentsRegistry::sharedProviderRegistry() { 15 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); 16 | 17 | // Custom Fabric Components go here. You can register custom 18 | // components coming from your App or from 3rd party libraries here. 19 | // 20 | // providerRegistry->add(concreteComponentDescriptorProvider< 21 | // AocViewerComponentDescriptor>()); 22 | return providerRegistry; 23 | } 24 | 25 | jni::local_ref 26 | MainComponentsRegistry::initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate) { 29 | auto instance = makeCxxInstance(delegate); 30 | 31 | auto buildRegistryFunction = 32 | [](EventDispatcher::Weak const &eventDispatcher, 33 | ContextContainer::Shared const &contextContainer) 34 | -> ComponentDescriptorRegistry::Shared { 35 | auto registry = MainComponentsRegistry::sharedProviderRegistry() 36 | ->createComponentDescriptorRegistry( 37 | {eventDispatcher, contextContainer}); 38 | 39 | auto mutableRegistry = 40 | std::const_pointer_cast(registry); 41 | 42 | mutableRegistry->setFallbackComponentDescriptor( 43 | std::make_shared( 44 | ComponentDescriptorParameters{ 45 | eventDispatcher, contextContainer, nullptr})); 46 | 47 | return registry; 48 | }; 49 | 50 | delegate->buildRegistryFunction = buildRegistryFunction; 51 | return instance; 52 | } 53 | 54 | void MainComponentsRegistry::registerNatives() { 55 | registerHybrid({ 56 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), 57 | }); 58 | } 59 | 60 | } // namespace react 61 | } // namespace facebook 62 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainComponentsRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | class MainComponentsRegistry 12 | : public facebook::jni::HybridClass { 13 | public: 14 | // Adapt it to the package you used for your Java class. 15 | constexpr static auto kJavaDescriptor = 16 | "Lcom/toolkitexample/newarchitecture/components/MainComponentsRegistry;"; 17 | 18 | static void registerNatives(); 19 | 20 | MainComponentsRegistry(ComponentFactory *delegate); 21 | 22 | private: 23 | static std::shared_ptr 24 | sharedProviderRegistry(); 25 | 26 | static jni::local_ref initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate); 29 | }; 30 | 31 | } // namespace react 32 | } // namespace facebook 33 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/OnLoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MainApplicationTurboModuleManagerDelegate.h" 3 | #include "MainComponentsRegistry.h" 4 | 5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 6 | return facebook::jni::initialize(vm, [] { 7 | facebook::react::MainApplicationTurboModuleManagerDelegate:: 8 | registerNatives(); 9 | facebook::react::MainComponentsRegistry::registerNatives(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ToolkitExample 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | import org.apache.tools.ant.taskdefs.condition.Os 2 | 3 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 4 | 5 | buildscript { 6 | ext { 7 | buildToolsVersion = "31.0.0" 8 | minSdkVersion = 21 9 | compileSdkVersion = 31 10 | targetSdkVersion = 31 11 | 12 | if (System.properties['os.arch'] == "aarch64") { 13 | // For M1 Users we need to use the NDK 24 which added support for aarch64 14 | ndkVersion = "24.0.8215888" 15 | } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { 16 | // For Android Users, we need to use NDK 23, otherwise the build will 17 | // fail due to paths longer than the OS limit 18 | ndkVersion = "23.1.7779620" 19 | } else { 20 | // Otherwise we default to the side-by-side NDK version from AGP. 21 | ndkVersion = "21.4.7075529" 22 | } 23 | } 24 | repositories { 25 | google() 26 | mavenCentral() 27 | } 28 | dependencies { 29 | classpath("com.android.tools.build:gradle:7.0.4") 30 | classpath("com.facebook.react:react-native-gradle-plugin") 31 | classpath("de.undercouch:gradle-download-task:4.1.2") 32 | // NOTE: Do not place your application dependencies here; they belong 33 | // in the individual module build.gradle files 34 | } 35 | } 36 | 37 | allprojects { 38 | repositories { 39 | maven { 40 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 41 | url("$rootDir/../node_modules/react-native/android") 42 | } 43 | maven { 44 | // Android JSC is installed from npm 45 | url("$rootDir/../node_modules/jsc-android/dist") 46 | } 47 | mavenCentral { 48 | // We don't want to fetch react-native from Maven Central as there are 49 | // older versions over there. 50 | content { 51 | excludeGroup "com.facebook.react" 52 | } 53 | } 54 | google() 55 | maven { url 'https://www.jitpack.io' } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.125.0 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=false 41 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ToolkitExample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/react-native-gradle-plugin') 5 | 6 | if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { 7 | include(":ReactAndroid") 8 | project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') 9 | } 10 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ToolkitExample", 3 | "displayName": "ToolkitExample" 4 | } -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '11.0' 5 | install! 'cocoapods', :deterministic_uuids => false 6 | 7 | target 'ToolkitExample' do 8 | config = use_native_modules! 9 | 10 | # Flags change depending on the env values. 11 | flags = get_default_flags() 12 | 13 | use_react_native!( 14 | :path => config[:reactNativePath], 15 | # to enable hermes on iOS, change `false` to `true` and then install pods 16 | :hermes_enabled => flags[:hermes_enabled], 17 | :fabric_enabled => flags[:fabric_enabled], 18 | # An absolute path to your application root. 19 | :app_path => "#{Pod::Config.instance.installation_root}/.." 20 | ) 21 | 22 | target 'ToolkitExampleTests' do 23 | inherit! :complete 24 | # Pods for testing 25 | end 26 | 27 | # Enables Flipper. 28 | # 29 | # Note that if you have use_frameworks! enabled, Flipper will not work and 30 | # you should disable the next line. 31 | use_flipper!() 32 | 33 | post_install do |installer| 34 | react_native_post_install(installer) 35 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample.xcodeproj/xcshareddata/xcschemes/ToolkitExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | #import 8 | 9 | #if RCT_NEW_ARCH_ENABLED 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | #import 18 | 19 | @interface AppDelegate () { 20 | RCTTurboModuleManager *_turboModuleManager; 21 | RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; 22 | std::shared_ptr _reactNativeConfig; 23 | facebook::react::ContextContainer::Shared _contextContainer; 24 | } 25 | @end 26 | #endif 27 | 28 | @implementation AppDelegate 29 | 30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 31 | { 32 | RCTAppSetupPrepareApp(application); 33 | 34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 35 | 36 | #if RCT_NEW_ARCH_ENABLED 37 | _contextContainer = std::make_shared(); 38 | _reactNativeConfig = std::make_shared(); 39 | _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); 40 | _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer]; 41 | bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; 42 | #endif 43 | 44 | UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"ToolkitExample", nil); 45 | 46 | if (@available(iOS 13.0, *)) { 47 | rootView.backgroundColor = [UIColor systemBackgroundColor]; 48 | } else { 49 | rootView.backgroundColor = [UIColor whiteColor]; 50 | } 51 | 52 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 53 | UIViewController *rootViewController = [UIViewController new]; 54 | rootViewController.view = rootView; 55 | self.window.rootViewController = rootViewController; 56 | [self.window makeKeyAndVisible]; 57 | return YES; 58 | } 59 | 60 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 61 | { 62 | #if DEBUG 63 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 64 | #else 65 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 66 | #endif 67 | } 68 | 69 | #if RCT_NEW_ARCH_ENABLED 70 | 71 | #pragma mark - RCTCxxBridgeDelegate 72 | 73 | - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge 74 | { 75 | _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge 76 | delegate:self 77 | jsInvoker:bridge.jsCallInvoker]; 78 | return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager); 79 | } 80 | 81 | #pragma mark RCTTurboModuleManagerDelegate 82 | 83 | - (Class)getModuleClassFromName:(const char *)name 84 | { 85 | return RCTCoreModulesClassProvider(name); 86 | } 87 | 88 | - (std::shared_ptr)getTurboModule:(const std::string &)name 89 | jsInvoker:(std::shared_ptr)jsInvoker 90 | { 91 | return nullptr; 92 | } 93 | 94 | - (std::shared_ptr)getTurboModule:(const std::string &)name 95 | initParams: 96 | (const facebook::react::ObjCTurboModule::InitParams &)params 97 | { 98 | return nullptr; 99 | } 100 | 101 | - (id)getModuleInstanceFromClass:(Class)moduleClass 102 | { 103 | return RCTAppSetupDefaultModuleFromClass(moduleClass); 104 | } 105 | 106 | #endif 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ToolkitExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/ToolkitExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /example/ios/ToolkitExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/ToolkitExampleTests/ToolkitExampleTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface ToolkitExampleTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation ToolkitExampleTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: true, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ToolkitExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "ios:pods": "npx pod-install", 9 | "start": "react-native start", 10 | "test": "jest", 11 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx" 12 | }, 13 | "dependencies": { 14 | "react": "17.0.2", 15 | "react-native": "0.68.1", 16 | "react-native-app-toolkit": "link:../" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.12.9", 20 | "@babel/runtime": "^7.12.5", 21 | "@react-native-community/eslint-config": "^2.0.0", 22 | "@types/jest": "^26.0.23", 23 | "@types/react-native": "^0.67.3", 24 | "@types/react-test-renderer": "^17.0.1", 25 | "@typescript-eslint/eslint-plugin": "^5.17.0", 26 | "@typescript-eslint/parser": "^5.17.0", 27 | "babel-jest": "^26.6.3", 28 | "eslint": "^7.32.0", 29 | "jest": "^26.6.3", 30 | "metro-react-native-babel-preset": "^0.67.0", 31 | "react-test-renderer": "17.0.2", 32 | "typescript": "^4.4.4" 33 | }, 34 | "resolutions": { 35 | "@types/react": "^17" 36 | }, 37 | "jest": { 38 | "preset": "react-native", 39 | "moduleFileExtensions": [ 40 | "ts", 41 | "tsx", 42 | "js", 43 | "jsx", 44 | "json", 45 | "node" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * React Native App Toolkit Example 3 | * https://github.com/luoxuhai/react-native-app-toolkit 4 | * 5 | * @format 6 | */ 7 | 8 | import React from 'react'; 9 | import { 10 | SafeAreaView, 11 | ScrollView, 12 | StatusBar, 13 | StyleSheet, 14 | Text, 15 | useColorScheme, 16 | View, 17 | } from 'react-native'; 18 | import * as Toolkit from 'react-native-app-toolkit'; 19 | import { 20 | Colors, 21 | DebugInstructions, 22 | Header, 23 | LearnMoreLinks, 24 | ReloadInstructions, 25 | } from 'react-native/Libraries/NewAppScreen'; 26 | 27 | const Section: React.FC<{ 28 | title: string; 29 | }> = ({children, title}) => { 30 | const isDarkMode = useColorScheme() === 'dark'; 31 | return ( 32 | 33 | 40 | {title} 41 | 42 | 49 | {children} 50 | 51 | 52 | ); 53 | }; 54 | 55 | const App = () => { 56 | const isDarkMode = useColorScheme() === 'dark'; 57 | 58 | const backgroundStyle = { 59 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 60 | }; 61 | 62 | return ( 63 | 64 | 65 | 68 |

69 | 73 |
74 | Edit App.tsx to change this 75 | screen and then come back to see your edits. 76 |
77 |
78 | 79 |
80 |
81 | 82 |
83 |
84 | Read the docs to discover what to do next: 85 |
86 | 87 |
88 | 89 | 90 | ); 91 | }; 92 | 93 | const styles = StyleSheet.create({ 94 | sectionContainer: { 95 | marginTop: 32, 96 | paddingHorizontal: 24, 97 | }, 98 | sectionTitle: { 99 | fontSize: 24, 100 | fontWeight: '600', 101 | }, 102 | sectionDescription: { 103 | marginTop: 8, 104 | fontSize: 18, 105 | fontWeight: '400', 106 | }, 107 | highlight: { 108 | fontWeight: '700', 109 | }, 110 | }); 111 | 112 | export default App; 113 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "compilerOptions": { 4 | /* Basic Options */ 5 | "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | "lib": ["es2017"], /* Specify library files to be included in the compilation. */ 8 | "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | "jsx": "react-native", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "removeComments": true, /* Do not emit comments to output. */ 17 | "noEmit": true, /* Do not emit outputs. */ 18 | // "incremental": true, /* Enable incremental compilation */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | 38 | /* Module Resolution Options */ 39 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 40 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 46 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 49 | "resolveJsonModule": true /* Allows importing modules with a ‘.json’ extension, which is a common practice in node projects. */ 50 | 51 | /* Source Map Options */ 52 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 53 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 56 | 57 | /* Experimental Options */ 58 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 59 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 60 | }, 61 | "exclude": [ 62 | "node_modules", "babel.config.js", "metro.config.js", "jest.config.js" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/.gitignore: -------------------------------------------------------------------------------- 1 | # xcode noise 2 | build/ 3 | *.pbxuser 4 | *.mode1v3 5 | *.mode2v3 6 | *.perspectivev3 7 | xcuserdata/ 8 | *.xccheckout 9 | 10 | # old skool 11 | .svn 12 | 13 | # osx noise 14 | .DS_Store 15 | profile 16 | 17 | # vim noise 18 | *~ 19 | *.swp 20 | 21 | # AppCode noise 22 | .idea/ 23 | 24 | # Ruby 25 | .ruby-version 26 | 27 | # Carthage 28 | Carthage/Build 29 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11.2 3 | 4 | before_install: 5 | - env 6 | - locale 7 | - xcpretty --version 8 | - xcodebuild -version 9 | - xcodebuild -showsdks 10 | 11 | script: 12 | - set -o pipefail 13 | 14 | - xcodebuild clean build -workspace MBProgressHUD.xcworkspace -scheme HudDemo -sdk iphonesimulator -configuration Debug | xcpretty -c 15 | - xcodebuild clean build -workspace MBProgressHUD.xcworkspace -scheme HudDemoTV -sdk appletvsimulator -configuration Debug | xcpretty -c 16 | - xcodebuild clean build test -workspace MBProgressHUD.xcworkspace -scheme HudTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPad Air (3rd generation),OS=13.2.2" -configuration Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c 17 | 18 | after_success: 19 | - bash <(curl -s https://codecov.io/bash) 20 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/CHANGELOG.mdown: -------------------------------------------------------------------------------- 1 | **Version 1.0.0** @ 14.07.16 2 | 3 | - Requires ARC and iOS 6+. 4 | - Includes a new default design for iOS 7+. 5 | - Deprecates certain helpers and exposes some more flexible API. 6 | - Removes KVO observing of local properties. 7 | - Migrates layout code to Auto Layout. 8 | - Includes a rewritten demo app. 9 | - Includes a rewritten iOS example app. 10 | - Updates and extends documentation. 11 | - Adds a new button property (cancellation support). 12 | - Adds support for `NSProgress` 13 | - Adds a new customizable background view class. 14 | - Adds new assertions. 15 | - Adds basic unit tests. 16 | - Adds support for motion effects. 17 | - Adds nullability. 18 | - Adds basic interface builder support. 19 | - Adds tvOS support. 20 | - Adds a simple tvOS example app. 21 | - Improves behavior when showing and hiding in quick succession. 22 | - Improves support for `UIAppearance `. 23 | - Various smaller bug-fixes 24 | 25 | **Version 0.9.2** @ 22.12.15 26 | 27 | - Timer improvements 28 | - Additional assertions 29 | - Added a framework target 30 | - Tint progress tint color enhancements 31 | 32 | **Version 0.9.1** @ 06.03.15 33 | 34 | - Bug-fixes 35 | - Modernization 36 | 37 | **Version 0.9** @ 12.08.14 38 | 39 | - iOS 8 compatibility and some bug fixes. 40 | - Additional iOS 7 / iOS 8 styling enhancements. 41 | - Improved 64bit support. 42 | - Demo modernization. 43 | 44 | **Version 0.8** @ 19.09.13 45 | 46 | - iOS 7 compatibility and some bug fixes. 47 | 48 | **Version 0.7** @ 25.06.13 49 | 50 | - Added horizontal bar mode. ([jjxtra](https://github.com/jjxtra)). 51 | - CI integration. 52 | 53 | **Version 0.6** @ 13.03.13 54 | 55 | - Full cocoapods support. 56 | - Static library integration option. 57 | - Improved blocks support. 58 | - Bezel color. 59 | - Demo app fixes (iOS 6). 60 | - Various bug-fixes and enhancements. 61 | 62 | **Version 0.5** @ 22.03.12 63 | 64 | - Major source code modernization and cleanup (KVO, layout code, instance vars, etc.). 65 | - New annular determinate mode. 66 | - New text only mode. 67 | - Added a static library project and Xcode 4 workspace. 68 | - Added methods to find and return HUD(s) on a view. 69 | - Various bug fixes. 70 | - Various demo project enhancements (hi-res rescues, new samples). 71 | 72 | IMPORTANT: Requires LLVM 3+. 73 | 74 | **Version 0.41** @ 03.01.12 75 | 76 | - Support for ARC. 77 | 78 | **Version 0.4** @ 25.07.10 79 | 80 | - Different animation modes. Default set to zoom. 81 | - Class convenience methods ([tadelv](http://github.com/tadelv)). 82 | - Autorotation when added to a UIWindow ([wuf810](http://github.com/wuf810)). 83 | - Extended demo app. 84 | - Several smaller fixes. 85 | 86 | **Version 0.33** @ 27.03.10 87 | 88 | - Custom view operation mode added. 89 | - Fixed a memory leak. 90 | 91 | **Version 0.32** @ 4.01.10 92 | 93 | - Added minShowTime, graceTime, xOffset, yOffset. 94 | - Various fixes. 95 | 96 | **Version 0.31** @ 8.10.09 97 | 98 | - Fix for touch through during the fade-out animation. 99 | 100 | **Version 0.3** @ 30.9.09 101 | 102 | - Added show: and hide: methods. 103 | - Now using UIViews layoutSubviews to automate layout calls. 104 | - Added some floors to round pixel positions and thereby prevent unsharp views. 105 | - Some additional documentation and code cleanup. 106 | 107 | **Version 0.2** @ 21.7.09 108 | 109 | - Added determinate progress mode and switching capabilities between determinate and indeterminate modes. 110 | - Various bug-fixes. 111 | 112 | **Version 0.11** @ 2.6.09. 113 | 114 | - Updated labelText and detailsLabelText properties to support text modifications while the HUD is being shown. 115 | 116 | **Version 0.1** @ 2.4.09 117 | 118 | - Initial release. 119 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please take a moment to review this document in order to make the contribution 2 | process easy and effective for everyone involved. 3 | 4 | 5 | # Using the issue tracker 6 | 7 | The issue tracker is the preferred channel for [bug reports](#bugs) and 8 | [features requests](#features), but please respect the following restriction: 9 | 10 | * Please **do not** use the issue tracker for personal support requests (use 11 | a service like [Stack Overflow](http://stackoverflow.com) instead). 12 | 13 | 14 | ## Bug reports 15 | 16 | A bug is a _demonstrable problem_ that is caused by the code in the repository. 17 | Good bug reports are extremely helpful - thank you! 18 | 19 | Guidelines for bug reports: 20 | 21 | 1. **Use the GitHub issue search** — check if the issue has already been 22 | reported. 23 | 24 | 2. **Check if the issue has been fixed** — try to reproduce it using the 25 | latest `master` branch in the repository. 26 | 27 | 3. **Isolate the problem** — provide exact reproduction steps, preferably 28 | in the form of a failing test case or by providing modification steps in the 29 | `MBProgressHUD` Demo application. 30 | 31 | A good bug report shouldn't leave others needing to chase you up for more 32 | information. Please try to be as detailed as possible in your report. What is 33 | your environment? What steps will reproduce the issue? What iOS version did 34 | you use? What would you expect to be the outcome? 35 | 36 | 37 | 38 | ## Feature requests 39 | 40 | Feature requests are welcome. But take a moment to find out whether your idea 41 | fits with the scope and aims of the project. It's up to *you* to make a strong 42 | case to convince the project's developers of the merits of this feature. Please 43 | provide as much detail and context as possible. 44 | 45 | 46 | 47 | # Pull requests 48 | 49 | Good pull requests - patches, improvements, new features - are a fantastic 50 | help. They should remain focused in scope and avoid containing unrelated 51 | commits. 52 | 53 | **Please ask first** before embarking on any significant pull request (e.g. 54 | implementing features, refactoring code, porting to a different language), 55 | otherwise you risk spending a lot of time working on something that the 56 | project's developers might not want to merge into the project. 57 | 58 | Please adhere to the coding conventions used throughout a project (indentation, 59 | accurate comments, etc.) and any other requirements (such as test coverage). 60 | 61 | **IMPORTANT**: By submitting a patch, you agree to allow the project owner to 62 | license your work under the same license as that used by the project. 63 | 64 | This document is based on https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md. 65 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/Framework-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2009-2020 Matej Bukovinski 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MBProgressHUD' target in the 'MBProgressHUD' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_8_0 8 | #warning "This project uses features only available in iOS SDK 8.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import 15 | #endif 16 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MBProgressHUD" 3 | s.version = "1.2.0" 4 | s.summary = "An iOS activity indicator view." 5 | s.description = <<-DESC 6 | MBProgressHUD is an iOS drop-in class that displays a translucent HUD 7 | with an indicator and/or labels while work is being done in a background thread. 8 | The HUD is meant as a replacement for the undocumented, private UIKit UIProgressHUD 9 | with some additional features. 10 | DESC 11 | s.homepage = "http://www.bukovinski.com" 12 | s.license = { :type => 'MIT', :file => 'LICENSE' } 13 | s.author = { 'Matej Bukovinski' => 'matej@bukovinski.com' } 14 | s.source = { :git => "https://github.com/matej/MBProgressHUD.git", :tag => s.version.to_s } 15 | s.ios.deployment_target = '9.0' 16 | s.tvos.deployment_target = '9.0' 17 | s.source_files = '*.{h,m}' 18 | s.frameworks = "CoreGraphics", "QuartzCore" 19 | s.requires_arc = true 20 | end 21 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD Framework tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD Framework.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/MBProgressHUD.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/README.mdown: -------------------------------------------------------------------------------- 1 | # MBProgressHUD 2 | 3 | [![Build Status](https://travis-ci.org/matej/MBProgressHUD.svg?branch=master)](https://travis-ci.org/matej/MBProgressHUD) [![codecov.io](https://codecov.io/github/matej/MBProgressHUD/coverage.svg?branch=master)](https://codecov.io/github/matej/MBProgressHUD?branch=master) 4 | [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) [![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio) [![CocoaPods compatible](https://img.shields.io/cocoapods/v/MBProgressHUD.svg?style=flat)](https://cocoapods.org/pods/MBProgressHUD) [![License: MIT](https://img.shields.io/cocoapods/l/MBProgressHUD.svg?style=flat)](http://opensource.org/licenses/MIT) 5 | 6 | `MBProgressHUD` is an iOS drop-in class that displays a translucent HUD with an indicator and/or labels while work is being done in a background thread. The HUD is meant as a replacement for the undocumented, private `UIKit` `UIProgressHUD` with some additional features. 7 | 8 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1.png) 9 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2.png) 10 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3.png) 11 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4.png) 12 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5.png) 13 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6.png) 14 | [![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7.png) 15 | 16 | ## Requirements 17 | 18 | `MBProgressHUD` works on iOS 9.0+. It depends on the following Apple frameworks, which should already be included with most Xcode templates: 19 | 20 | * Foundation.framework 21 | * UIKit.framework 22 | * CoreGraphics.framework 23 | 24 | You will need the latest developer tools in order to build `MBProgressHUD`. Old Xcode versions might work, but compatibility will not be explicitly maintained. 25 | 26 | ## Adding MBProgressHUD to your project 27 | 28 | ### CocoaPods 29 | 30 | [CocoaPods](http://cocoapods.org) is the recommended way to add MBProgressHUD to your project. 31 | 32 | 1. Add a pod entry for MBProgressHUD to your Podfile `pod 'MBProgressHUD', '~> 1.2.0'` 33 | 2. Install the pod(s) by running `pod install`. 34 | 3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. 35 | 36 | ### Carthage 37 | 38 | 1. Add MBProgressHUD to your Cartfile. e.g., `github "jdg/MBProgressHUD" ~> 1.2.0` 39 | 2. Run `carthage update` 40 | 3. Follow the rest of the [standard Carthage installation instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add MBProgressHUD to your project. 41 | 42 | ### SwiftPM / Accio 43 | 44 | 1. Add the following to your `Package.swift`: 45 | ```swift 46 | .package(url: "https://github.com/jdg/MBProgressHUD.git", .upToNextMajor(from: "1.2.0")), 47 | ``` 48 | 2. Next, add `MBProgressHUD` to your App targets dependencies like so: 49 | ```swift 50 | .target(name: "App", dependencies: ["MBProgressHUD"]), 51 | ``` 52 | 3. Then open your project in Xcode 11+ (SwiftPM) or run `accio update` (Accio). 53 | 54 | ### Source files 55 | 56 | Alternatively you can directly add the `MBProgressHUD.h` and `MBProgressHUD.m` source files to your project. 57 | 58 | 1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. 59 | 2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. 60 | 3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. 61 | 62 | ### Static library 63 | 64 | You can also add MBProgressHUD as a static library to your project or workspace. 65 | 66 | 1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. 67 | 2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). 68 | 3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. 69 | 4. Include MBProgressHUD wherever you need it with `#import `. 70 | 71 | ## Usage 72 | 73 | The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. 74 | 75 | ```objective-c 76 | [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 77 | dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 78 | // Do something... 79 | dispatch_async(dispatch_get_main_queue(), ^{ 80 | [MBProgressHUD hideHUDForView:self.view animated:YES]; 81 | }); 82 | }); 83 | ``` 84 | 85 | You can add the HUD on any view or window. It is however a good idea to avoid adding the HUD to certain `UIKit` views with complex view hierarchies - like `UITableView` or `UICollectionView`. Those can mutate their subviews in unexpected ways and thereby break HUD display. 86 | 87 | If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. 88 | 89 | ```objective-c 90 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 91 | hud.mode = MBProgressHUDModeAnnularDeterminate; 92 | hud.label.text = @"Loading"; 93 | [self doSomethingInBackgroundWithProgressCallback:^(float progress) { 94 | hud.progress = progress; 95 | } completionCallback:^{ 96 | [hud hideAnimated:YES]; 97 | }]; 98 | ``` 99 | 100 | You can also use a `NSProgress` object and MBProgressHUD will update itself when there is progress reported through that object. 101 | 102 | ```objective-c 103 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 104 | hud.mode = MBProgressHUDModeAnnularDeterminate; 105 | hud.label.text = @"Loading"; 106 | NSProgress *progress = [self doSomethingInBackgroundCompletion:^{ 107 | [hud hideAnimated:YES]; 108 | }]; 109 | hud.progressObject = progress; 110 | ``` 111 | 112 | Keep in mind that UI updates, including calls to MBProgressHUD should always be done on the main thread. 113 | 114 | If you need to run your long-running task in the main thread, you should perform it with a slight delay, so UIKit will have enough time to update the UI (i.e., draw the HUD) before you block the main thread with your task. 115 | 116 | ```objective-c 117 | [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 118 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC); 119 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 120 | // Do something... 121 | [MBProgressHUD hideHUDForView:self.view animated:YES]; 122 | }); 123 | ``` 124 | 125 | You should be aware that any HUD updates issued inside the above block won't be displayed until the block completes. 126 | 127 | For more examples, including how to use MBProgressHUD with asynchronous operations such as NSURLConnection, take a look at the bundled demo project. Extensive API documentation is provided in the header file (MBProgressHUD.h). 128 | 129 | 130 | ## License 131 | 132 | This code is distributed under the terms and conditions of the [MIT license](LICENSE). 133 | 134 | ## Change-log 135 | 136 | A brief summary of each MBProgressHUD release can be found in the [CHANGELOG](CHANGELOG.mdown). 137 | 138 | ## Privacy 139 | 140 | MBProgressHUD does not collect any data. See [SDK Privacy Practices](https://bukovinski.com/sdk-privacy/mbprogresshud/) for more information. 141 | -------------------------------------------------------------------------------- /ios/MBProgressHUD/include/MBProgressHUD/MBProgressHUD.h: -------------------------------------------------------------------------------- 1 | ../../MBProgressHUD.h -------------------------------------------------------------------------------- /ios/MBProgressHUD/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module MBProgressHUD { 2 | umbrella header "MBProgressHUD/MBProgressHUD.h" 3 | export * 4 | module * { export * } 5 | } 6 | -------------------------------------------------------------------------------- /ios/RCTConvert+RNToolkit.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | @import UIKit; 4 | 5 | @interface RCTConvert(RNToolkit) 6 | 7 | + (UIModalPresentationStyle)UIModalPresentationStyle:(NSString*)value; 8 | + (UIModalTransitionStyle)UIModalTransitionStyle:(NSString*)value; 9 | + (UIImagePickerControllerQualityType)UIImagePickerControllerQualityType:(NSString*)value; 10 | + (QLThumbnailGenerationRequestRepresentationTypes)QLThumbnailGenerationRequestRepresentationTypes:(NSString*)value API_AVAILABLE(ios(13.0)); 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ios/RCTConvert+RNToolkit.m: -------------------------------------------------------------------------------- 1 | #import "RCTConvert+RNToolkit.h" 2 | 3 | @implementation RCTConvert(RNToolkit) 4 | 5 | + (UIModalPresentationStyle)defaultModalPresentationStyle { 6 | if (@available(iOS 13.0, *)) { 7 | return UIModalPresentationAutomatic; 8 | } else { 9 | return UIModalPresentationFullScreen; 10 | } 11 | } 12 | 13 | RCT_ENUM_CONVERTER(UIModalTransitionStyle, (@{ 14 | @"coverVertical" : @(UIModalTransitionStyleCoverVertical), 15 | @"flipHorizontal" : @(UIModalTransitionStyleFlipHorizontal), 16 | @"crossDissolve" : @(UIModalTransitionStyleCrossDissolve), 17 | @"partialCurl" : @(UIModalTransitionStylePartialCurl) 18 | }), 19 | UIModalTransitionStyleCoverVertical, integerValue) 20 | 21 | RCT_ENUM_CONVERTER(UIModalPresentationStyle, (@{ 22 | @"fullScreen" : @(UIModalPresentationFullScreen), 23 | @"pageSheet" : @(UIModalPresentationPageSheet), 24 | @"formSheet" : @(UIModalPresentationFormSheet), 25 | @"currentContext" : @(UIModalPresentationCurrentContext), 26 | @"custom" : @(UIModalPresentationCustom), 27 | @"overFullScreen" : @(UIModalPresentationOverFullScreen), 28 | @"overCurrentContext" : @(UIModalPresentationOverCurrentContext), 29 | @"popover" : @(UIModalPresentationPopover), 30 | @"none" : @(UIModalPresentationNone), 31 | @"default" : @([RCTConvert defaultModalPresentationStyle]) 32 | }), 33 | UIModalPresentationFullScreen, integerValue) 34 | 35 | RCT_ENUM_CONVERTER(UIImagePickerControllerQualityType,(@{ 36 | @"high" : @(UIImagePickerControllerQualityTypeHigh), 37 | @"640x480" : @(UIImagePickerControllerQualityType640x480), 38 | @"medium" : @(UIImagePickerControllerQualityTypeMedium), 39 | @"low" : @(UIImagePickerControllerQualityTypeLow), 40 | @"iFrame1280x720" : @(UIImagePickerControllerQualityTypeIFrame1280x720), 41 | @"iFrame960x540" : @(UIImagePickerControllerQualityTypeIFrame960x540), 42 | }), 43 | UIImagePickerControllerQualityTypeHigh, integerValue) 44 | 45 | RCT_ENUM_CONVERTER(QLThumbnailGenerationRequestRepresentationTypes,(@{ 46 | @"icon" : @(QLThumbnailGenerationRequestRepresentationTypeIcon), 47 | @"lowQualityThumbnail" : @(QLThumbnailGenerationRequestRepresentationTypeLowQualityThumbnail), 48 | @"thumbnail" : @(QLThumbnailGenerationRequestRepresentationTypeThumbnail), 49 | @"all" : @(QLThumbnailGenerationRequestRepresentationTypeAll), 50 | }), 51 | QLThumbnailGenerationRequestRepresentationTypeThumbnail, integerValue) 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /ios/RNToolkit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentCamera.h 3 | // RNToolkit 4 | // 5 | // Created by https://github.com/luoxuhai on 2022/4/9. 6 | // 7 | 8 | #import 9 | 10 | @interface RNToolkit : NSObject 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ios/RNToolkit.m: -------------------------------------------------------------------------------- 1 | #import "RNToolkit.h" 2 | 3 | static NSString* const TMP_DIRECTORY = @"react-native-kit/"; 4 | 5 | @interface RNToolkit() 6 | 7 | @end 8 | 9 | @implementation RNToolkit 10 | 11 | - (instancetype)init { 12 | NSString *directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 13 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 14 | 15 | BOOL isDir = YES; 16 | BOOL exists = [fileManager fileExistsAtPath:directory isDirectory:&isDir]; 17 | if (!exists) { 18 | [fileManager createDirectoryAtPath: directory 19 | withIntermediateDirectories:YES attributes:nil error:nil]; 20 | } 21 | return self; 22 | } 23 | 24 | RCT_EXPORT_MODULE(RNToolkit) 25 | 26 | RCT_EXPORT_METHOD(init:(RCTPromiseResolveBlock)resolve 27 | rejecter:(RCTPromiseRejectBlock)reject) 28 | { 29 | NSString *directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 30 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 31 | 32 | BOOL isDir = YES; 33 | BOOL exists = [fileManager fileExistsAtPath:directory isDirectory:&isDir]; 34 | if (!exists) { 35 | [fileManager createDirectoryAtPath: directory 36 | withIntermediateDirectories:YES attributes:nil error:nil]; 37 | } 38 | resolve(directory); 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ios/RTKAppearance.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RTKAppearance : NSObject 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /ios/RTKAppearance.m: -------------------------------------------------------------------------------- 1 | #import "RNToolkit.h" 2 | #import "RTKAppearance.h" 3 | 4 | @implementation RNToolkit 5 | 6 | RCT_EXPORT_MODULE(RTKAppearance) 7 | 8 | RCT_EXPORT_METHOD(setAppearanceColorScheme:(NSString *)style 9 | withResolver:(RCTPromiseResolveBlock)resolve 10 | withRejecter:(RCTPromiseRejectBlock)reject) 11 | { 12 | if (@available(iOS 13.0, *)) { 13 | dispatch_async(dispatch_get_main_queue(), ^{ 14 | UIWindow *window = UIApplication.sharedApplication.delegate.window; 15 | if ([style isEqual:@"light"]) { 16 | window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; 17 | } else if ([style isEqual:@"dark"]) { 18 | window.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; 19 | } else { 20 | window.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified; 21 | } 22 | }); 23 | resolve(nil); 24 | } else { 25 | reject(@"ERROR", @"Only available on iOS 13.0 or newer", nil); 26 | } 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ios/RTKDocumentCamera.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef NS_ENUM(NSInteger, RTKDocumentCameraResultType) { 4 | RTKResultPdf, 5 | RTKResultImage 6 | }; 7 | 8 | @interface RTKDocumentCamera : NSObject 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/RTKDocumentCamera.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import "RTKDocumentCamera.h" 6 | 7 | static NSString* const TMP_DIRECTORY = @"react-native-kit/"; 8 | 9 | @implementation RCTConvert (RTKDocumentCameraResultType) 10 | 11 | RCT_ENUM_CONVERTER( 12 | RTKDocumentCameraResultType, 13 | (@{ 14 | @"pdf" : @(RTKResultPdf), 15 | @"image" : @(RTKResultImage) 16 | }), 17 | RTKResultPdf, 18 | integerValue) 19 | @end 20 | 21 | @interface RTKDocumentCamera() 22 | 23 | @property (nonatomic, copy) NSDictionary *options; 24 | @property (nonatomic, copy) NSString *directory; 25 | @property (nonatomic, copy) RCTPromiseResolveBlock resolve; 26 | @property (nonatomic, copy) RCTPromiseRejectBlock reject; 27 | 28 | @end 29 | 30 | @implementation RTKDocumentCamera 31 | 32 | - (instancetype)init { 33 | if ((self = [super init])) { 34 | self.directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 35 | } 36 | return self; 37 | } 38 | 39 | RCT_EXPORT_MODULE(RTKDocumentCamera) 40 | 41 | RCT_EXPORT_METHOD(openDocumentCamera:(NSDictionary *)options 42 | resolver:(RCTPromiseResolveBlock)resolve 43 | rejecter:(RCTPromiseRejectBlock)reject) 44 | { 45 | self.resolve = resolve; 46 | self.reject = reject; 47 | self.options = options; 48 | 49 | dispatch_async(dispatch_get_main_queue(), ^{ 50 | if (@available(iOS 13.0, *)) { 51 | if (VNDocumentCameraViewController.isSupported) { 52 | VNDocumentCameraViewController* documentCameraViewController = [[VNDocumentCameraViewController alloc] init]; 53 | 54 | documentCameraViewController.delegate = self; 55 | 56 | UIViewController *rootViewController = RCTPresentedViewController(); 57 | [rootViewController presentViewController:documentCameraViewController animated:YES completion:nil]; 58 | } else { 59 | self.reject(@"ERROR",@"The current device doesn't support document scanning", nil); 60 | } 61 | } else { 62 | self.reject(@"ERROR", @"Only available on iOS 13.0 or newer", nil); 63 | } 64 | }); 65 | } 66 | 67 | RCT_EXPORT_METHOD(isSupported:(RCTPromiseResolveBlock)resolve 68 | rejecter:(RCTPromiseRejectBlock)reject) 69 | { 70 | if (@available(iOS 13.0, *)) { 71 | resolve(@(VNDocumentCameraViewController.isSupported)); 72 | } else { 73 | resolve(@(NO)); 74 | } 75 | } 76 | 77 | - (void) dismissViewController: (VNDocumentCameraViewController *)controller API_AVAILABLE(ios(13.0)){ 78 | [controller dismissViewControllerAnimated:YES completion:nil]; 79 | } 80 | 81 | - (NSString *) imagesToPDF: (NSMutableArray *)images { 82 | PDFDocument *pdfDocument = [PDFDocument new]; 83 | 84 | for (int i = 0; i < images.count; i++) { 85 | PDFPage *pdfPage = [[PDFPage alloc] initWithImage:images[i]]; 86 | [pdfDocument insertPage:pdfPage atIndex:i]; 87 | } 88 | NSData *data = [pdfDocument dataRepresentation]; 89 | NSString *dest = [NSString stringWithFormat:@"%@%@.%@", self.directory, [[NSUUID UUID] UUIDString], @"pdf"]; 90 | if (![data writeToFile:dest atomically:YES]) { 91 | self.reject(@"ERROR", @"Can't write to file.", nil); 92 | return nil; 93 | } 94 | return dest; 95 | } 96 | 97 | #pragma mark - VNDocumentCameraViewControllerDelegate 98 | 99 | - (void)documentCameraViewController:(VNDocumentCameraViewController *)controller didFinishWithScan:(VNDocumentCameraScan *)scan API_AVAILABLE(ios(13.0)) API_AVAILABLE(ios(13.0)){ 100 | NSString *typeStr = self.options[@"type"]; 101 | RTKDocumentCameraResultType type = [RCTConvert RTKDocumentCameraResultType:typeStr]; 102 | 103 | NSMutableArray *images = [NSMutableArray new]; 104 | for (int i = 0; i < [scan pageCount]; i++) { 105 | UIImage* image = [scan imageOfPageAtIndex:i]; 106 | [images addObject:image]; 107 | } 108 | 109 | if (type == RTKResultImage) { 110 | NSMutableArray *source = [NSMutableArray new]; 111 | NSNumber *quality = self.options[@"quality"]; 112 | 113 | for (int i = 0; i < [images count]; i++) { 114 | NSString *dest = [NSString stringWithFormat:@"%@%@.%@", self.directory, [[NSUUID UUID] UUIDString], @"jpg"]; 115 | NSData *data = UIImageJPEGRepresentation(images[i], [quality floatValue]); 116 | if (![data writeToFile:dest atomically:YES]) { 117 | self.reject(@"ERROR", @"Can't write to file.", nil); 118 | [self dismissViewController:controller]; 119 | return; 120 | } 121 | [source addObject:dest]; 122 | } 123 | self.resolve(@{ 124 | @"type":self.options[@"type"], 125 | @"source":source 126 | }); 127 | } else { 128 | NSString *pdfPath = [self imagesToPDF:images]; 129 | if (pdfPath) { 130 | self.resolve(@{ 131 | @"type":self.options[@"type"], 132 | @"source":pdfPath 133 | }); 134 | } 135 | } 136 | 137 | [self dismissViewController:controller]; 138 | } 139 | 140 | - (void)documentCameraViewControllerDidCancel:(VNDocumentCameraViewController *)controller API_AVAILABLE(ios(13.0)){ 141 | [self dismissViewController:controller]; 142 | } 143 | 144 | - (void)documentCameraViewController:(VNDocumentCameraViewController *)controller didFailWithError:(NSError *)error API_AVAILABLE(ios(13)){ 145 | self.reject(@"ERROR", error.localizedDescription, error); 146 | [self dismissViewController:controller]; 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /ios/RTKMediaLibrary.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RTKMediaLibrary : NSObject 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /ios/RTKMediaLibrary.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import "RTKMediaLibrary.h" 5 | 6 | static NSString* const OPTIONS_KEY_QUALITY = @"quality"; 7 | static NSString* const OPTIONS_KEY_TIME = @"time"; 8 | static NSString* const OPTIONS_KEY_INCLUDE_SIZE = @"includeSize"; 9 | static NSString* const TMP_DIRECTORY = @"react-native-kit/"; 10 | static NSString* const OPTIONS_KEY_HEADERS = @"headers"; 11 | 12 | @interface RTKMediaLibrary() 13 | 14 | @property (nonatomic, copy) NSString *directory; 15 | 16 | @end 17 | 18 | @implementation RTKMediaLibrary 19 | 20 | -(id)init { 21 | self.directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 22 | return self; 23 | } 24 | 25 | RCT_EXPORT_MODULE(RTKMediaLibrary) 26 | 27 | RCT_EXPORT_METHOD(getVideoThumbnail:(NSString *)path 28 | options:( NSDictionary *)options 29 | resolver:(RCTPromiseResolveBlock)resolve 30 | rejecter:(RCTPromiseRejectBlock)reject) 31 | { 32 | NSURL *url = [NSURL URLWithString:path]; 33 | long timeOption = [options[OPTIONS_KEY_TIME] integerValue] ?: 0; 34 | float quality = [options[OPTIONS_KEY_QUALITY] floatValue] ?: 0; 35 | BOOL includeSize = [options[OPTIONS_KEY_INCLUDE_SIZE] boolValue] ?: NO; 36 | NSDictionary *headers = options[OPTIONS_KEY_HEADERS] ?: @{}; 37 | 38 | AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:@{@"AVURLAssetHTTPHeaderFieldsKey": headers}]; 39 | 40 | AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 41 | generator.appliesPreferredTrackTransform = YES; 42 | generator.requestedTimeToleranceBefore = kCMTimeZero; 43 | generator.requestedTimeToleranceAfter = kCMTimeZero; 44 | 45 | NSError *err = NULL; 46 | CMTime time = CMTimeMake(timeOption, 1000); 47 | 48 | CGImageRef imgRef = [generator copyCGImageAtTime:time actualTime:NULL error:&err]; 49 | if (err) { 50 | reject(@"ERROR",err.localizedFailureReason,nil); 51 | } 52 | 53 | UIImage *thumbnail = [UIImage imageWithCGImage:imgRef]; 54 | NSString *fileName = [[[NSUUID UUID] UUIDString] stringByAppendingString:@".jpg"]; 55 | NSString *dest = [self.directory stringByAppendingString:fileName]; 56 | 57 | NSData *data = UIImageJPEGRepresentation(thumbnail, quality); 58 | 59 | if (![data writeToFile:dest atomically:YES]) { 60 | reject(@"ERROR",@"Can't write to file.",nil); 61 | } 62 | 63 | NSNumber *fileSize = nil; 64 | 65 | if (includeSize) { 66 | [[NSURL fileURLWithPath:dest] getResourceValue:&fileSize 67 | forKey:NSURLFileSizeKey 68 | error:nil]; 69 | } 70 | 71 | CGImageRelease(imgRef); 72 | 73 | resolve(@{ 74 | @"uri": dest, 75 | @"width": @(thumbnail.size.width), 76 | @"height": @(thumbnail.size.height), 77 | @"size": (fileSize) ?: [NSNull null] 78 | }); 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /ios/RTKQuickLookView/RTKQuickLookManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface RTKQuickLookManager : RCTViewManager 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /ios/RTKQuickLookView/RTKQuickLookManager.m: -------------------------------------------------------------------------------- 1 | #import "RTKQuickLookManager.h" 2 | #import "RTKQuickLookView.h" 3 | #import 4 | 5 | @implementation RTKQuickLookManager 6 | 7 | RCT_EXPORT_MODULE(RTKQuickLook) 8 | 9 | - (UIView *) view { 10 | return [[RTKQuickLookView alloc] init]; 11 | } 12 | 13 | RCT_EXPORT_VIEW_PROPERTY(url, NSString) 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/RTKQuickLookView/RTKQuickLookView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RTKQuickLookView : UIView 4 | 5 | @property (nonatomic, copy) NSString *url; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /ios/RTKQuickLookView/RTKQuickLookView.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "RTKQuickLookView.h" 3 | 4 | @interface RTKQuickLookView () 5 | 6 | @property QLPreviewController* controller; 7 | 8 | @end 9 | 10 | 11 | @implementation RTKQuickLookView 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | [self initialize]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)initialize { 22 | self.controller = [[QLPreviewController alloc] init]; 23 | self.controller.delegate = self; 24 | self.controller.dataSource = self; 25 | self.controller.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 26 | self.controller.view.backgroundColor = UIColor.blackColor; 27 | [self addSubview:self.controller.view]; 28 | } 29 | 30 | - (id)initWithPreviewItemUrl:(NSString*)url { 31 | NSAssert(url != nil, @"Preview Item URL cannot be nil"); 32 | self = [super init]; 33 | if (self) { 34 | _url = url; 35 | [self initialize]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)setUrl:(NSString *)urlString { 41 | _url = [urlString stringByRemovingPercentEncoding]; 42 | [self.controller refreshCurrentPreviewItem]; 43 | [self.controller reloadData]; 44 | } 45 | 46 | #pragma mark - QLPreviewControllerDataSource 47 | 48 | - (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller { 49 | return 1; 50 | } 51 | 52 | - (id )previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index { 53 | return [NSURL fileURLWithPath:_url]; 54 | } 55 | 56 | #pragma mark - QLPreviewControllerDelegate 57 | 58 | - (BOOL)previewController:(QLPreviewController *)controller shouldOpenURL:(NSURL *)url forPreviewItem:(id )item { 59 | return YES; 60 | } 61 | 62 | - (void)didReceiveMemoryWarning { 63 | [self.controller didReceiveMemoryWarning]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ios/RTKThumbnailGenerator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RTKThumbnailGenerator : NSObject 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /ios/RTKThumbnailGenerator.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "RTKThumbnailGenerator.h" 4 | #import "RCTConvert+RNToolkit.h" 5 | 6 | static NSString* const TMP_DIRECTORY = @"react-native-kit/"; 7 | 8 | @interface RTKThumbnailGenerator() 9 | 10 | @property (nonatomic, copy) NSString *directory; 11 | 12 | @end 13 | 14 | 15 | @implementation RTKThumbnailGenerator 16 | 17 | - (id)init { 18 | if ((self = [super init])) { 19 | self.directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 20 | } 21 | return self; 22 | } 23 | 24 | RCT_EXPORT_MODULE(RTKThumbnailGenerator) 25 | 26 | RCT_EXPORT_METHOD(generate:(NSDictionary *)options 27 | resolver:(RCTPromiseResolveBlock)resolve 28 | rejecter:(RCTPromiseRejectBlock)reject) { 29 | if (@available(iOS 14.0, *)) { 30 | NSURL *url = [NSURL fileURLWithPath:options[@"path"]]; 31 | CGFloat scale = [options[@"scale"] floatValue] ?: UIScreen.mainScreen.scale; 32 | CGSize size = {[options[@"width"] floatValue], [options[@"height"] floatValue]}; 33 | NSString *dest = [NSString stringWithFormat:@"%@%@.%@", self.directory, [[NSUUID UUID] UUIDString], @"jpg"]; 34 | NSURL *toFileAtURL = [NSURL fileURLWithPath:options[@"toFileAtURL"] ?: dest ]; 35 | BOOL iconMode = [options[@"iconMode"] boolValue] ?: NO; 36 | CGFloat minimumDimension = [options[@"minimumDimension"] floatValue] ?: 0; 37 | 38 | QLThumbnailGenerationRequestRepresentationTypes representationType = [RCTConvert QLThumbnailGenerationRequestRepresentationTypes:options[@"representationType"]]; 39 | 40 | 41 | QLThumbnailGenerationRequest *request = [[QLThumbnailGenerationRequest alloc] initWithFileAtURL:url 42 | size:size 43 | scale:scale 44 | representationTypes:representationType]; 45 | request.iconMode = iconMode; 46 | request.minimumDimension = minimumDimension; 47 | 48 | [QLThumbnailGenerator.sharedGenerator saveBestRepresentationForRequest:request 49 | toFileAtURL:toFileAtURL 50 | withContentType:UTTypeJPEG.identifier 51 | completionHandler:^(NSError * _Nullable error) { 52 | if (error) { 53 | reject(@"ERROR", error.localizedDescription, error); 54 | } else { 55 | resolve(@{ 56 | @"path": [toFileAtURL absoluteString] 57 | }); 58 | } 59 | }]; 60 | 61 | } else { 62 | reject(@"ERROR", @"Only available on iOS 13.0 or newer", nil); 63 | } 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ios/RTKVideoEditor.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RTKVideoEditor : NSObject 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /ios/RTKVideoEditor.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import "RTKVideoEditor.h" 6 | #import "RCTConvert+RNToolkit.h" 7 | 8 | static NSString* const TMP_DIRECTORY = @"react-native-kit/"; 9 | 10 | @interface RTKVideoEditor() 11 | 12 | @property (nonatomic, copy) NSString *directory; 13 | @property (nonatomic, copy) RCTPromiseResolveBlock resolve; 14 | @property (nonatomic, copy) RCTPromiseRejectBlock reject; 15 | 16 | @end 17 | 18 | 19 | @implementation RTKVideoEditor 20 | 21 | - (instancetype)init { 22 | if ((self = [super init])) { 23 | self.directory = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; 24 | } 25 | return self; 26 | } 27 | 28 | RCT_EXPORT_MODULE(RTKVideoEditor) 29 | 30 | RCT_EXPORT_METHOD(openVideoEditor:(NSDictionary *)options 31 | resolver:(RCTPromiseResolveBlock)resolve 32 | rejecter:(RCTPromiseRejectBlock)reject) { 33 | self.resolve = resolve; 34 | self.reject = reject; 35 | int maxDuration = [options[@"maxDuration"] intValue] ?: 1; 36 | NSString *path = options[@"source"]; 37 | UIImagePickerControllerQualityType quality = [RCTConvert UIImagePickerControllerQualityType:options[@"quality"]]; 38 | UIModalPresentationStyle presentationStyle = [RCTConvert UIModalPresentationStyle:options[@"presentationStyle"]]; 39 | UIModalTransitionStyle transitionStyle = [RCTConvert UIModalTransitionStyle:options[@"transitionStyle"]]; 40 | 41 | if (path == nil) { 42 | reject(@"ERROR", @"Source cannot be nil", nil); 43 | return; 44 | } 45 | 46 | dispatch_async(dispatch_get_main_queue(), ^{ 47 | UIVideoEditorController *videoEditorController = [UIVideoEditorController new]; 48 | videoEditorController.videoPath = path; 49 | videoEditorController.videoMaximumDuration = maxDuration; 50 | videoEditorController.videoQuality = quality; 51 | videoEditorController.modalPresentationStyle = presentationStyle; 52 | videoEditorController.modalTransitionStyle = transitionStyle; 53 | videoEditorController.delegate = self; 54 | 55 | UIViewController *rootViewController = RCTPresentedViewController(); 56 | [rootViewController presentViewController:videoEditorController animated:YES completion:nil]; 57 | }); 58 | } 59 | 60 | RCT_EXPORT_METHOD(canEdit:(NSString *)path 61 | resolver:(RCTPromiseResolveBlock)resolve 62 | rejecter:(RCTPromiseRejectBlock)reject) { 63 | resolve(@([UIVideoEditorController canEditVideoAtPath:path])); 64 | } 65 | 66 | #pragma mark - UIVideoEditorControllerDelegate 67 | 68 | - (void)videoEditorController:(UIVideoEditorController *)editor didSaveEditedVideoToPath:(NSString *)editedVideoPath { 69 | self.resolve(@{ @"uri": editedVideoPath }); 70 | [editor dismissViewControllerAnimated:YES completion:nil]; 71 | } 72 | 73 | - (void)videoEditorController:(UIVideoEditorController *)editor didFailWithError:(NSError *)error { 74 | self.reject(@"ERROR", error.localizedDescription, nil); 75 | [editor dismissViewControllerAnimated:YES completion:nil]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-app-toolkit", 3 | "version": "1.0.0", 4 | "description": "High-quality toolkit for React Native using native code.", 5 | "main": "lib/commonjs/index", 6 | "module": "lib/module/index", 7 | "types": "lib/typescript/index.d.ts", 8 | "react-native": "src/index", 9 | "source": "src/index", 10 | "files": [ 11 | "src", 12 | "lib", 13 | "android", 14 | "ios", 15 | "cpp", 16 | "react-native-app-toolkit.podspec", 17 | "!lib/typescript/example", 18 | "!android/build", 19 | "!ios/build", 20 | "!**/__tests__", 21 | "!**/__fixtures__", 22 | "!**/__mocks__" 23 | ], 24 | "scripts": { 25 | "test": "jest", 26 | "typescript": "tsc --noEmit", 27 | "lint": "eslint \"**/*.{js,ts,tsx}\"", 28 | "prepare": "bob build", 29 | "build": "bob build", 30 | "release": "release-it", 31 | "example": "yarn --cwd example", 32 | "pods": "cd example && pod-install --quiet", 33 | "bootstrap": "yarn example && yarn && yarn pods", 34 | "dev-sync": "yarn build && mr example/node_modules/@react-native-library/kit/ios && cp -r package.json *podspec lib android ios src example/node_modules/@react-native-library/kit/", 35 | "example:ios": "cd example && yarn ios", 36 | "example:install:pods": "cd example && yarn ios:pods", 37 | "example:start": "cd example && yarn start" 38 | }, 39 | "keywords": [ 40 | "react-native", 41 | "ios", 42 | "android", 43 | "toolkit" 44 | ], 45 | "repository": "https://github.com/luoxuhai/react-native-app-toolkit", 46 | "author": "luoxuhai (https://github.com/luoxuhai)", 47 | "license": "MIT", 48 | "bugs": { 49 | "url": "https://github.com/luoxuhai/react-native-app-toolkit/issues" 50 | }, 51 | "homepage": "https://github.com/luoxuhai/react-native-app-toolkit#readme", 52 | "publishConfig": { 53 | "registry": "https://registry.npmjs.org/" 54 | }, 55 | "devDependencies": { 56 | "@commitlint/config-conventional": "^11.0.0", 57 | "@react-native-community/eslint-config": "^2.0.0", 58 | "@release-it/conventional-changelog": "^2.0.0", 59 | "@types/jest": "^26.0.0", 60 | "@types/react": "^16.9.19", 61 | "@types/react-native": "0.62.13", 62 | "commitlint": "^11.0.0", 63 | "eslint": "^7.2.0", 64 | "eslint-config-prettier": "^7.0.0", 65 | "eslint-plugin-prettier": "^3.1.3", 66 | "husky": "^6.0.0", 67 | "jest": "^26.0.1", 68 | "pod-install": "^0.1.0", 69 | "prettier": "^2.0.5", 70 | "react": "16.13.1", 71 | "react-native": "0.63.4", 72 | "react-native-builder-bob": "^0.18.0", 73 | "release-it": "^14.2.2", 74 | "typescript": "^4.1.3" 75 | }, 76 | "peerDependencies": { 77 | "react": "*", 78 | "react-native": "*" 79 | }, 80 | "jest": { 81 | "preset": "react-native", 82 | "modulePathIgnorePatterns": [ 83 | "/example/node_modules", 84 | "/lib/" 85 | ] 86 | }, 87 | "commitlint": { 88 | "extends": [ 89 | "@commitlint/config-conventional" 90 | ] 91 | }, 92 | "release-it": { 93 | "git": { 94 | "commitMessage": "chore: release ${version}", 95 | "tagName": "v${version}" 96 | }, 97 | "npm": { 98 | "publish": true 99 | }, 100 | "github": { 101 | "release": true 102 | }, 103 | "plugins": { 104 | "@release-it/conventional-changelog": { 105 | "preset": "angular" 106 | } 107 | } 108 | }, 109 | "eslintConfig": { 110 | "root": true, 111 | "extends": [ 112 | "@react-native-community", 113 | "prettier" 114 | ], 115 | "rules": { 116 | "prettier/prettier": [ 117 | "error", 118 | { 119 | "quoteProps": "consistent", 120 | "singleQuote": true, 121 | "tabWidth": 2, 122 | "trailingComma": "es5", 123 | "useTabs": false 124 | } 125 | ] 126 | } 127 | }, 128 | "eslintIgnore": [ 129 | "node_modules/", 130 | "lib/" 131 | ], 132 | "prettier": { 133 | "quoteProps": "consistent", 134 | "singleQuote": true, 135 | "tabWidth": 2, 136 | "trailingComma": "es5", 137 | "useTabs": false 138 | }, 139 | "react-native-builder-bob": { 140 | "source": "src", 141 | "output": "lib", 142 | "targets": [ 143 | "commonjs", 144 | "module", 145 | [ 146 | "typescript", 147 | { 148 | "project": "tsconfig.build.json" 149 | } 150 | ] 151 | ] 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /react-native-app-toolkit.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "react-native-app-toolkit" 7 | s.version = package["version"] 8 | s.summary = package["description"] 9 | s.homepage = package["homepage"] 10 | s.license = package["license"] 11 | s.authors = package["author"] 12 | 13 | s.platforms = { :ios => "11.0" } 14 | s.source = { :git => "https://github.com/luoxuhai/react-native-app-toolkit.git", :tag => "#{s.version}" } 15 | 16 | s.source_files = "ios/**/*.{h,m,mm}" 17 | 18 | s.dependency "React-Core" 19 | end 20 | -------------------------------------------------------------------------------- /scripts/bootstrap.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const path = require('path'); 3 | const child_process = require('child_process'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | const args = process.argv.slice(2); 7 | const options = { 8 | cwd: process.cwd(), 9 | env: process.env, 10 | stdio: 'inherit', 11 | encoding: 'utf-8', 12 | }; 13 | 14 | if (os.type() === 'Windows_NT') { 15 | options.shell = true 16 | } 17 | 18 | let result; 19 | 20 | if (process.cwd() !== root || args.length) { 21 | // We're not in the root of the project, or additional arguments were passed 22 | // In this case, forward the command to `yarn` 23 | result = child_process.spawnSync('yarn', args, options); 24 | } else { 25 | // If `yarn` is run without arguments, perform bootstrap 26 | result = child_process.spawnSync('yarn', ['bootstrap'], options); 27 | } 28 | 29 | process.exitCode = result.status; 30 | -------------------------------------------------------------------------------- /src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | it.todo('write a test'); 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as QuickLook from './packages/QuickLook'; 2 | import * as Appearance from './packages/Appearance'; 3 | import * as DocumentCamera from './packages/DocumentCamera'; 4 | import * as VideoEditor from './packages/VideoEditor'; 5 | import * as VideoThumbnail from './packages/VideoThumbnail'; 6 | import * as ThumbnailGenerator from './packages/ThumbnailGenerator'; 7 | 8 | export { 9 | QuickLook, 10 | Appearance, 11 | DocumentCamera, 12 | VideoEditor, 13 | VideoThumbnail, 14 | ThumbnailGenerator, 15 | }; 16 | -------------------------------------------------------------------------------- /src/internal/nativeInterface.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, Platform } from 'react-native'; 2 | 3 | const LINKING_ERROR = 4 | `The package 'react-native-app-toolkit' doesn't seem to be linked. Make sure: \n\n` + 5 | Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + 6 | '- You rebuilt the app after installing the package\n' + 7 | '- You are not using Expo managed workflow\n'; 8 | 9 | let { 10 | RNToolkit, 11 | RTKMediaLibrary, 12 | RTKVideoEditor, 13 | RTKAppearance, 14 | RTKDocumentCamera, 15 | RTKThumbnailGenerator, 16 | } = NativeModules; 17 | 18 | if (!RNToolkit) { 19 | RNToolkit = new Proxy( 20 | {}, 21 | { 22 | get() { 23 | throw new Error(LINKING_ERROR); 24 | }, 25 | } 26 | ); 27 | } 28 | 29 | RNToolkit.init(); 30 | 31 | export { 32 | RNToolkit, 33 | RTKMediaLibrary, 34 | RTKVideoEditor, 35 | RTKAppearance, 36 | RTKDocumentCamera, 37 | RTKThumbnailGenerator, 38 | }; 39 | -------------------------------------------------------------------------------- /src/packages/Appearance.tsx: -------------------------------------------------------------------------------- 1 | import type { ColorSchemeName } from 'react-native'; 2 | 3 | import { RTKAppearance } from '../internal/nativeInterface'; 4 | 5 | export function setAppearanceColorScheme( 6 | colorsSchemeName: ColorSchemeName 7 | ): Promise { 8 | return RTKAppearance.setAppearanceColorScheme(colorsSchemeName); 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/DocumentCamera.tsx: -------------------------------------------------------------------------------- 1 | import { RTKDocumentCamera } from '../internal/nativeInterface'; 2 | 3 | /** 4 | * Shows what the document camera sees. 5 | * @returns Promise 6 | */ 7 | export function open( 8 | options?: DocumentCameraOptions 9 | ): Promise { 10 | return RTKDocumentCamera.openDocumentCamera({ 11 | type: 'pdf', 12 | quality: 1, 13 | ...options, 14 | }); 15 | } 16 | 17 | export function isSupported() { 18 | return RTKDocumentCamera.isSupported(); 19 | } 20 | -------------------------------------------------------------------------------- /src/packages/QuickLook.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { requireNativeComponent, ViewProps } from 'react-native'; 3 | 4 | interface QuickLookViewProps extends ViewProps { 5 | /** 6 | * An URI of the file, local or remote. 7 | */ 8 | url?: string; 9 | } 10 | 11 | function QuickLookView(props: QuickLookViewProps) { 12 | return ; 13 | } 14 | 15 | export { QuickLookView as View }; 16 | 17 | var RTKQuickLookView = requireNativeComponent('RTKQuickLook'); 18 | -------------------------------------------------------------------------------- /src/packages/ThumbnailGenerator.tsx: -------------------------------------------------------------------------------- 1 | import { RTKThumbnailGenerator } from '../internal/nativeInterface'; 2 | 3 | /** 4 | * Generate thumbnails for common file types 5 | */ 6 | export function generate( 7 | options?: ThumbnailGeneratorOptions 8 | ): Promise { 9 | return RTKThumbnailGenerator.generate(options); 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/VideoEditor.tsx: -------------------------------------------------------------------------------- 1 | import { RTKVideoEditor } from '../internal/nativeInterface'; 2 | 3 | /** 4 | * Open a video editor for trimming video frames. 5 | * @returns Promise 6 | */ 7 | export function open( 8 | source: string, 9 | options?: VideoEditorOptions 10 | ): Promise { 11 | return RTKVideoEditor.openVideoEditor({ 12 | source, 13 | maxDuration: 600, 14 | quality: 'high', 15 | ...options, 16 | }); 17 | } 18 | 19 | /** 20 | * Returns a Boolean value indicating whether a video file can be edited. 21 | * @returns Promise 22 | */ 23 | export function canEdit(source: string): Promise { 24 | return RTKVideoEditor.canEdit(source); 25 | } 26 | -------------------------------------------------------------------------------- /src/packages/VideoThumbnail.tsx: -------------------------------------------------------------------------------- 1 | import { RTKMediaLibrary } from '../internal/nativeInterface'; 2 | 3 | export function getThumbnail( 4 | path: string, 5 | options?: VideoThumbnailOptions 6 | ): Promise { 7 | return RTKMediaLibrary.getVideoThumbnail(path, options); 8 | } 9 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | type TransitionStyle = 2 | | 'coverVertical' 3 | | 'flipHorizontal' 4 | | 'crossDissolve' 5 | | 'partialCurl'; 6 | 7 | type PresentationStyle = 8 | | 'fullScreen' 9 | | 'pageSheet' 10 | | 'formSheet' 11 | | 'popover' 12 | | 'none' 13 | | 'currentContext' 14 | | 'overFullScreen' 15 | | 'overCurrentContext' 16 | | 'default'; 17 | 18 | interface VideoThumbnailOptions { 19 | /** 20 | * 输出图像质量 21 | * 22 | * @default 1 23 | */ 24 | quality?: number; 25 | /** 26 | * 截取时间点 27 | * 28 | * @default 0 29 | */ 30 | time?: number; 31 | /** 32 | * 返回的结果中是否包含图像文件大小 33 | * 34 | * @default false 35 | */ 36 | includeSize?: boolean; 37 | /** 38 | * 网络视频资源的请求头 39 | */ 40 | headers?: Record; 41 | } 42 | 43 | interface VideoThumbnailResult { 44 | uri?: string; 45 | width?: number; 46 | height?: number; 47 | size?: number; 48 | } 49 | 50 | type DocumentCameraResultType = 'pdf' | 'image'; 51 | 52 | interface DocumentCameraOptions { 53 | /** 54 | * @default 'pdf' 55 | */ 56 | type?: DocumentCameraResultType; 57 | /** 58 | * @default 1 59 | */ 60 | quality?: number; 61 | } 62 | 63 | interface DocumentCameraResult { 64 | type: DocumentCameraResultType; 65 | source: string | string[]; 66 | } 67 | 68 | interface VideoEditorOptions { 69 | /** 70 | * The maximum duration, in seconds, permitted for trimmed movies saved by the video editor. 71 | * The system-enforced maximum duration for a video recording is 10 minutes; you can set this value to 10 minutes or less. The default value for this property is also 10 minutes. 72 | * @default 600 73 | */ 74 | maxDuration?: number; 75 | /** 76 | * @default 'high' 77 | */ 78 | quality?: 'high' | 'medium' | 'low'; 79 | /** 80 | * @default 'overFullScreen' 81 | */ 82 | transitionStyle?: TransitionStyle; 83 | /** 84 | * @default 'coverVertical' 85 | */ 86 | presentationStyle?: PresentationStyle; 87 | } 88 | 89 | interface VideoEditorResult { 90 | uri: string; 91 | // width: number; 92 | // height: number; 93 | // duration: number; 94 | // size: number; 95 | } 96 | 97 | interface ThumbnailGeneratorOptions { 98 | path: string; 99 | width: number; 100 | height: number; 101 | scale?: number; 102 | /** 103 | * @default false 104 | */ 105 | iconMode?: boolean; 106 | /** 107 | * @default 0 108 | */ 109 | minimumDimension?: number; 110 | toFileAtURL?: string; 111 | /** 112 | * @default 'thumbnail' 113 | */ 114 | representationType?: 'icon' | 'lowQualityThumbnail' | 'thumbnail'; 115 | } 116 | 117 | interface ThumbnailGeneratorResult { 118 | path: string; 119 | } 120 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["example", "website"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "react-native-kit": ["./src/index"] 6 | }, 7 | "allowUnreachableCode": false, 8 | "allowUnusedLabels": false, 9 | "esModuleInterop": true, 10 | "importsNotUsedAsValues": "error", 11 | "forceConsistentCasingInFileNames": true, 12 | "jsx": "react", 13 | "lib": ["esnext"], 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitReturns": true, 18 | "noImplicitUseStrict": false, 19 | "noStrictGenericChecks": false, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "resolveJsonModule": true, 23 | "skipLibCheck": true, 24 | "strict": true, 25 | "target": "esnext" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/blog/2019-05-28-first-blog-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: first-blog-post 3 | title: First Blog Post 4 | authors: 5 | name: Gao Wei 6 | title: Docusaurus Core Team 7 | url: https://github.com/wgao19 8 | image_url: https://github.com/wgao19.png 9 | tags: [hola, docusaurus] 10 | --- 11 | 12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 13 | -------------------------------------------------------------------------------- /website/blog/2019-05-29-long-blog-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: long-blog-post 3 | title: Long Blog Post 4 | authors: endi 5 | tags: [hello, docusaurus] 6 | --- 7 | 8 | This is the summary of a very long blog post, 9 | 10 | Use a `` comment to limit blog post size in the list view. 11 | 12 | 13 | 14 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 15 | 16 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 17 | 18 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 19 | 20 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 21 | 22 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 23 | 24 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 25 | 26 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 27 | 28 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 29 | 30 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 31 | 32 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 33 | 34 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 35 | 36 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 37 | 38 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 39 | 40 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 41 | 42 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 43 | 44 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 45 | -------------------------------------------------------------------------------- /website/blog/2021-08-01-mdx-blog-post.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | slug: mdx-blog-post 3 | title: MDX Blog Post 4 | authors: [slorber] 5 | tags: [docusaurus] 6 | --- 7 | 8 | Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). 9 | 10 | :::tip 11 | 12 | Use the power of React to create interactive blog posts. 13 | 14 | ```js 15 | 16 | ``` 17 | 18 | 19 | 20 | ::: 21 | -------------------------------------------------------------------------------- /website/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg -------------------------------------------------------------------------------- /website/blog/2021-08-26-welcome/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: welcome 3 | title: Welcome 4 | authors: [slorber, yangshun] 5 | tags: [facebook, hello, docusaurus] 6 | --- 7 | 8 | [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). 9 | 10 | Simply add Markdown files (or folders) to the `blog` directory. 11 | 12 | Regular blog authors can be added to `authors.yml`. 13 | 14 | The blog post date can be extracted from filenames, such as: 15 | 16 | - `2019-05-30-welcome.md` 17 | - `2019-05-30-welcome/index.md` 18 | 19 | A blog post folder can be convenient to co-locate blog post images: 20 | 21 | ![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) 22 | 23 | The blog supports tags as well! 24 | 25 | **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. 26 | -------------------------------------------------------------------------------- /website/blog/authors.yml: -------------------------------------------------------------------------------- 1 | endi: 2 | name: Endilie Yacop Sucipto 3 | title: Maintainer of Docusaurus 4 | url: https://github.com/endiliey 5 | image_url: https://github.com/endiliey.png 6 | 7 | yangshun: 8 | name: Yangshun Tay 9 | title: Front End Engineer @ Facebook 10 | url: https://github.com/yangshun 11 | image_url: https://github.com/yangshun.png 12 | 13 | slorber: 14 | name: Sébastien Lorber 15 | title: Docusaurus maintainer 16 | url: https://sebastienlorber.com 17 | image_url: https://github.com/slorber.png 18 | -------------------------------------------------------------------------------- /website/docs/api/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "API", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /website/docs/api/appearance.md: -------------------------------------------------------------------------------- 1 | # Appearance 2 | 3 | Override the app's color scheme (light / dark / unspecified). 4 | 5 | ```typescript 6 | import { Appearance } from 'react-native-app-toolkit'; 7 | 8 | Toolkit.setAppearanceColorScheme('dark'); // 'dark' | 'light' | 'unspecified' | null 9 | ``` 10 | -------------------------------------------------------------------------------- /website/docs/api/document-camera.md: -------------------------------------------------------------------------------- 1 | # DocumentCamera 2 | 3 | Scan documents with the camera. 4 | 5 | ![Screenshot](/screenshot/IMG_2589.PNG) 6 | 7 | ```typescript 8 | import { DocumentCamera } from 'react-native-app-toolkit'; 9 | 10 | DocumentCamera.open({ 11 | type: 'image', 12 | quality: 0.8, 13 | }).then((result) => { 14 | /* 15 | { 16 | type: 'image', 17 | source: ['/private/Application/tmp/react-native-kit/9DE1991A-EFA0-4507-AA2E-6FC9E4BE3ADB.jpg'] 18 | } 19 | */ 20 | }); 21 | 22 | Toolkit.openDocumentCamera({ 23 | type: 'pdf', 24 | }).then((result) => { 25 | /* 26 | { 27 | type: 'pdf', 28 | source: "/private/Application/tmp/react-native-kit/9DE1991A-EFA0-4507-AA2E-6FC9E4BE3ADB.pdf" 29 | } 30 | */ 31 | }); 32 | ``` 33 | -------------------------------------------------------------------------------- /website/docs/api/quick-look.md: -------------------------------------------------------------------------------- 1 | # QuickLook 2 | 3 | Preview files using QuickLook framework. Support for local and remote files. 4 | QuickLook can generate previews for common file types, including: 5 | 6 | - iWork and Microsoft Office documents 7 | - Images 8 | - Live Photos 9 | - Text files 10 | - PDFs 11 | - Audio and video files 12 | - Augmented reality objects that use the usdz file format (iOS and iPadOS only) 13 | 14 | ### Example: 15 | 16 | ```tsx 17 | import { QuickLook } from 'react-native-app-toolkit'; 18 | 19 | function Home() { 20 | return ( 21 | 26 | ); 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /website/docs/api/thumbnail-generator.md: -------------------------------------------------------------------------------- 1 | # ThumbnailGenerator 2 | 3 | Generate thumbnails for common file types, including: 4 | 5 | - iWork and Microsoft Office documents 6 | - Images 7 | - Live Photos 8 | - Text files 9 | - PDFs 10 | - Audio and video files 11 | 12 | ```typescript 13 | import { ThumbnailGenerator } from 'react-native-app-toolkit'; 14 | 15 | ThumbnailGenerator.generate({ 16 | path: '/private/var/Application/9DE1991A-EFA0-4507-AA2E-6FC9E4BE3ADB.pdf', 17 | width: 100, 18 | height: 100, 19 | }).then((res) => { 20 | /* 21 | { 22 | path: "/private/Application/tmp/react-native-kit/9DE1991A-EFA0-4507-AA2E-6FC9E4BE3ADB.jpg" 23 | } 24 | */ 25 | }); 26 | ``` 27 | -------------------------------------------------------------------------------- /website/docs/api/video-editor.md: -------------------------------------------------------------------------------- 1 | # VideoEditor 2 | 3 | Open a video editor for trimming video frames. 4 | 5 | ```typescript 6 | import { VideoEditor } from 'react-native-app-toolkit'; 7 | 8 | VideoEditor.open( 9 | '/private/Application/tmp/react-native-kit/9DE1991A-EFA0-4507-AA2E-89C9E4BE3ADB.mp4', 10 | { 11 | maxDuration: 600, 12 | quality: 'high', 13 | } 14 | ).then((result) => { 15 | /* 16 | { 17 | uri: '/private/Application/tmp/react-native-kit/9DE1991A-EFA0-4507-ABCD-6FC9E4BE3ADB.mp4' 18 | } 19 | */ 20 | }); 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/api/video-thumbnail.md: -------------------------------------------------------------------------------- 1 | # VideoThumbnail 2 | 3 | Allows you to generate images from video files to use as thumbnails 4 | 5 | ```typescript 6 | import { VideoThumbnail } from 'react-native-app-toolkit'; 7 | 8 | VideoThumbnail.getThumbnail( 9 | 'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4', 10 | { 11 | time: 1000, // ms 12 | quality: 0.8, 13 | } 14 | ).then((res) => { 15 | // VideoThumbnailsResult 16 | }); 17 | ``` 18 | 19 | #### `VideoThumbnailsOptions` 20 | 21 | | Name | Type | Description | 22 | | --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | 23 | | **quality** | number | A value in range 0.0 - 1.0 specifying quality level of the result image. 1 means no compression (highest quality) and 0 the highest compression (lowest quality). | 24 | | **time** | number | The time position where the image will be retrieved in ms. | 25 | | **includeSize** | boolean | Include image file size | 26 | | **headers** | object | In case sourceFilename is a remote URI, headers object is passed in a network request. | 27 | | | 28 | 29 | #### `VideoThumbnailsResult` 30 | 31 | | Name | Type | Description | 32 | | ---------- | ------ | ---------------------------- | 33 | | **uri** | string | uri to the created image. | 34 | | **width** | number | Width of the created image. | 35 | | **height** | number | Height of the created image. | 36 | | **size** | number | Size of the created image. | 37 | -------------------------------------------------------------------------------- /website/docs/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Installation 6 | 7 | If you are using `react-native >= 0.60` you just need to do a simple: 8 | 9 | ```shell 10 | yarn add react-native-app-toolkit 11 | ``` 12 | 13 | Or if are using npm: 14 | 15 | ```shell 16 | npm i react-native-app-toolkit --save 17 | ``` 18 | 19 | After that, we need to install the dependencies to use the project on iOS(you can skip this part, if you are using this on Android). 20 | 21 | Now run a simple: `npx pod-install` or `cd ios && pod install`. After that, you should be able to use the library on both Platforms, iOS and Android. 22 | -------------------------------------------------------------------------------- /website/docs/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Troubleshooting 6 | -------------------------------------------------------------------------------- /website/docs/usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Usage 6 | 7 | ## Example 8 | 9 | ```tsx 10 | import { ThumbnailGenerator } from 'react-native-app-toolkit'; 11 | 12 | ThumbnailGenerator.generate({ 13 | path: '/private/var/Application/9DE1991A-EFA0-4507-AA2E-6FC9E4BE3ADB.pdf', 14 | width: 100, 15 | height: 100, 16 | }).then((res) => { 17 | // ThumbnailGeneratorResult 18 | }); 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require('prism-react-renderer/themes/github'); 5 | const darkCodeTheme = require('prism-react-renderer/themes/dracula'); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: 'React Native App Toolkit', 10 | tagline: 'High-quality toolkit for React Native using native code.', 11 | url: 'https://luoxuhai.github.com', 12 | baseUrl: '/react-native-app-toolkit/', 13 | onBrokenLinks: 'throw', 14 | onBrokenMarkdownLinks: 'warn', 15 | favicon: 'img/favicon.ico', 16 | organizationName: 'luoxuhai', // Usually your GitHub org/user name. 17 | projectName: 'react-native-app-toolkit', // Usually your repo name. 18 | trailingSlash: false, 19 | 20 | presets: [ 21 | [ 22 | 'classic', 23 | /** @type {import('@docusaurus/preset-classic').Options} */ 24 | ({ 25 | docs: { 26 | sidebarPath: require.resolve('./sidebars.js'), 27 | // Please change this to your repo. 28 | editUrl: 29 | 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', 30 | }, 31 | theme: { 32 | customCss: require.resolve('./src/css/custom.css'), 33 | }, 34 | }), 35 | ], 36 | ], 37 | 38 | themeConfig: 39 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 40 | ({ 41 | navbar: { 42 | title: 'react-native-app-toolkit', 43 | logo: { 44 | alt: 'Logo', 45 | src: 'img/logo.svg', 46 | }, 47 | items: [ 48 | { 49 | type: 'doc', 50 | docId: 'getting-started', 51 | position: 'left', 52 | label: 'Docs', 53 | }, 54 | { 55 | href: 'https://github.com/luoxuhai/react-native-app-toolkit', 56 | label: 'GitHub', 57 | position: 'right', 58 | }, 59 | ], 60 | }, 61 | footer: { 62 | style: 'dark', 63 | links: [ 64 | { 65 | title: 'Docs', 66 | items: [ 67 | { 68 | label: 'Installation', 69 | to: '/docs/getting-started', 70 | }, 71 | ], 72 | }, 73 | { 74 | title: 'Community', 75 | items: [ 76 | { 77 | label: 'Discussions', 78 | href: 'https://github.com/luoxuhai/react-native-app-toolkit/discussions', 79 | }, 80 | { 81 | label: 'Issues', 82 | href: 'https://github.com/luoxuhai/react-native-app-toolkit/issues', 83 | }, 84 | { 85 | label: 'Stack Overflow', 86 | href: 'https://stackoverflow.com/questions/tagged/react-native-app-toolkit', 87 | }, 88 | ], 89 | }, 90 | { 91 | title: 'More', 92 | items: [ 93 | { 94 | label: 'GitHub', 95 | href: 'https://github.com/luoxuhai/react-native-app-toolkit', 96 | }, 97 | { 98 | label: 'Twitter', 99 | href: 'https://twitter.com/LuoXuhai', 100 | }, 101 | ], 102 | }, 103 | ], 104 | copyright: `Copyright © ${new Date().getFullYear()} luoxuhai. Built with Docusaurus.`, 105 | }, 106 | prism: { 107 | theme: lightCodeTheme, 108 | darkTheme: darkCodeTheme, 109 | }, 110 | }), 111 | }; 112 | 113 | module.exports = config; 114 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-app-toolkit-website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@docusaurus/core": "2.0.0-beta.18", 18 | "@docusaurus/preset-classic": "2.0.0-beta.18", 19 | "@mdx-js/react": "^1.6.22", 20 | "clsx": "^1.1.1", 21 | "prism-react-renderer": "^1.3.1", 22 | "react": "^17.0.2", 23 | "react-dom": "^17.0.2" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.5%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | }, 37 | "devDependencies": { 38 | "@docusaurus/module-type-aliases": "^2.0.0-beta.18", 39 | "@tsconfig/docusaurus": "^1.0.5", 40 | "typescript": "^4.6.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [ 18 | { 19 | type: 'autogenerated', 20 | dirName: '.', 21 | // items: ['getting-started'], 22 | }, 23 | ], 24 | // componentsSidebar: [ 25 | // { 26 | // type: 'category', 27 | // label: 'Components', 28 | // items: ['components'], 29 | // }, 30 | // ], 31 | // apiSidebar: [ 32 | // { 33 | // type: 'category', 34 | // label: 'API', 35 | // items: ['api'], 36 | // }, 37 | // ], 38 | // hooksSidebar: [{}], 39 | // But you can create a sidebar manually 40 | /* 41 | tutorialSidebar: [ 42 | { 43 | type: 'category', 44 | label: 'Tutorial', 45 | items: ['hello'], 46 | }, 47 | ], 48 | */ 49 | }; 50 | 51 | module.exports = sidebars; 52 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './styles.module.css'; 4 | 5 | const FeatureList = [ 6 | { 7 | title: 'Easy to Use', 8 | Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, 9 | description: ( 10 | <> 11 | Docusaurus was designed from the ground up to be easily installed and 12 | used to get your website up and running quickly. 13 | 14 | ), 15 | }, 16 | { 17 | title: 'Focus on What Matters', 18 | Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, 19 | description: ( 20 | <> 21 | Docusaurus lets you focus on your docs, and we'll do the chores. Go 22 | ahead and move your docs into the docs directory. 23 | 24 | ), 25 | }, 26 | { 27 | title: 'Powered by React', 28 | Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, 29 | description: ( 30 | <> 31 | Extend or customize your website layout by reusing React. Docusaurus can 32 | be extended while reusing the same header and footer. 33 | 34 | ), 35 | }, 36 | ]; 37 | 38 | function Feature({ Svg, title, description }) { 39 | return ( 40 |
41 |
42 | 43 |
44 |
45 |

{title}

46 |

{description}

47 |
48 |
49 | ); 50 | } 51 | 52 | export default function HomepageFeatures() { 53 | return ( 54 |
55 |
56 |
57 | {FeatureList.map((props, idx) => ( 58 | 59 | ))} 60 |
61 |
62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | } 18 | 19 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 20 | [data-theme='dark'] { 21 | --ifm-color-primary: #25c2a0; 22 | --ifm-color-primary-dark: #21af90; 23 | --ifm-color-primary-darker: #1fa588; 24 | --ifm-color-primary-darkest: #1a8870; 25 | --ifm-color-primary-light: #29d5b0; 26 | --ifm-color-primary-lighter: #32d8b4; 27 | --ifm-color-primary-lightest: #4fddbf; 28 | } 29 | 30 | .docusaurus-highlight-code-line { 31 | background-color: rgba(0, 0, 0, 0.1); 32 | display: block; 33 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 34 | padding: 0 var(--ifm-pre-padding); 35 | } 36 | 37 | [data-theme='dark'] .docusaurus-highlight-code-line { 38 | background-color: rgba(0, 0, 0, 0.3); 39 | } 40 | -------------------------------------------------------------------------------- /website/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /website/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Layout from '@theme/Layout'; 4 | import Link from '@docusaurus/Link'; 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 6 | import styles from './index.module.css'; 7 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 8 | 9 | function HomepageHeader() { 10 | const { siteConfig } = useDocusaurusContext(); 11 | return ( 12 |
13 |
14 |

{siteConfig.title}

15 |

{siteConfig.tagline}

16 |
17 | 21 | Getting Started 22 | 23 |
24 |
25 |
26 | ); 27 | } 28 | 29 | export default function Home() { 30 | const { siteConfig } = useDocusaurusContext(); 31 | return ( 32 | 36 | 37 |
38 | 39 |
40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /website/src/pages/markdown-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown page example 3 | --- 4 | 5 | # Markdown page example 6 | 7 | You don't need React to write simple standalone pages. 8 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/img/docusaurus.png -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/static/img/tutorial/docsVersionDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/img/tutorial/docsVersionDropdown.png -------------------------------------------------------------------------------- /website/static/img/tutorial/localeDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/img/tutorial/localeDropdown.png -------------------------------------------------------------------------------- /website/static/screenshot/IMG_2589.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxuhai/react-native-app-toolkit/fdacdb36a434640c7878e0183e90183fc180d230/website/static/screenshot/IMG_2589.PNG -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/docusaurus/tsconfig.json" 3 | } 4 | --------------------------------------------------------------------------------