├── .buckconfig ├── .bundle └── config ├── .eslintrc.js ├── .gitignore ├── .node-version ├── .npmrc ├── .prettierrc.js ├── .ruby-version ├── .vscode └── settings.json ├── .watchmanconfig ├── Gemfile ├── README.md ├── __tests__ └── App-test.tsx ├── android ├── app │ ├── _BUCK │ ├── build.gradle │ ├── build_defs.bzl │ ├── debug.keystore │ ├── my-release-key.keystore │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── wowimrn │ │ │ └── ReactNativeFlipper.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── wowimrn │ │ │ ├── MainActivity.java │ │ │ ├── MainApplication.java │ │ │ ├── RCTButton.java │ │ │ ├── RCTButtonPackage.java │ │ │ ├── ToastModule.java │ │ │ └── newarchitecture │ │ │ ├── MainApplicationReactNativeHost.java │ │ │ ├── components │ │ │ └── MainComponentsRegistry.java │ │ │ └── modules │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ ├── jni │ │ ├── CMakeLists.txt │ │ ├── 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 │ │ ├── colors.xml │ │ ├── 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 ├── docs ├── README.md └── RNCamera.js ├── fix-camera.sh ├── iconfont.json ├── index.js ├── ios ├── .xcode.env ├── CustomButton.m ├── MyButton.h ├── MyButton.m ├── MyButtonManager.h ├── MyButtonManager.m ├── Podfile ├── Podfile.lock ├── RNTMapManager.m ├── WowImRN.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── WowImRN.xcscheme ├── WowImRN.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── WowImRN │ ├── AppDelegate.h │ ├── AppDelegate.mm │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Info.plist │ ├── LaunchScreen.storyboard │ └── main.m └── WowImRNTests │ ├── Info.plist │ └── WowImRNTests.m ├── metro.config.js ├── package-lock.json ├── package.json ├── react-native.config.js ├── screenshot ├── animate.gif ├── fs.png ├── full_bg.png ├── home.png ├── login_screen.png ├── me_login.png ├── me_un_login.png ├── scan.png ├── wx.jpeg └── wx.png ├── src ├── App.tsx ├── assets │ ├── animation │ │ ├── ani.json │ │ └── bounce-fruit.json │ ├── iconfont │ │ ├── IconCameraFill.tsx │ │ ├── IconCart.tsx │ │ ├── IconCartO.tsx │ │ ├── IconContact.tsx │ │ ├── IconContactO.tsx │ │ ├── IconEye.tsx │ │ ├── IconFile.tsx │ │ ├── IconFile1.tsx │ │ ├── IconHome.tsx │ │ ├── IconHomeO.tsx │ │ ├── IconManage.tsx │ │ ├── IconManageO.tsx │ │ ├── IconNoEye.tsx │ │ ├── IconPeople.tsx │ │ ├── IconPeopleO.tsx │ │ ├── IconPhotoFill.tsx │ │ ├── IconPositionFill.tsx │ │ ├── IconVideoCallFill.tsx │ │ ├── IconVoiceFill.tsx │ │ ├── helper.ts │ │ └── index.tsx │ └── img │ │ ├── account.png │ │ ├── account_o.png │ │ ├── arrow_left.png │ │ ├── avatar.png │ │ ├── cart.png │ │ ├── cart_o.png │ │ ├── find.png │ │ ├── find_o.png │ │ ├── home.png │ │ ├── home_o.png │ │ └── loading.gif ├── baseUI │ ├── BButton │ │ └── index.tsx │ ├── BEmpty │ │ └── index.tsx │ ├── BHStack │ │ └── index.tsx │ ├── BImagePicker │ │ └── index.tsx │ ├── BInput │ │ └── index.tsx │ ├── BLine │ │ └── index.tsx │ ├── BList │ │ └── index.tsx │ ├── BListItem │ │ └── index.tsx │ ├── BPage │ │ ├── BNPage.tsx │ │ ├── BNavBar.tsx │ │ └── index.tsx │ ├── BRefreshControl │ │ └── index.tsx │ ├── BRow │ │ └── index.tsx │ ├── BSegment │ │ ├── Item.tsx │ │ └── index.tsx │ ├── BShadow │ │ └── index.tsx │ ├── BText │ │ └── index.tsx │ ├── BTextArea │ │ └── index.tsx │ ├── BVStack │ │ └── index.tsx │ ├── Loading │ │ ├── index.tsx │ │ ├── loading_01.gif │ │ ├── loading_02.gif │ │ ├── loading_03.gif │ │ ├── loading_04.gif │ │ ├── loading_05.gif │ │ ├── loading_06.gif │ │ └── loading_07.gif │ ├── MTouchableOpacity │ │ └── index.tsx │ ├── TabBarIcon │ │ └── index.tsx │ └── icon │ │ ├── IconArrowLeft.tsx │ │ ├── IconArrowRight.tsx │ │ ├── IconClose.tsx │ │ ├── IconIosArrowRoundBack.tsx │ │ ├── IconKongbai1.tsx │ │ └── helper.ts ├── config │ ├── index.ts │ ├── request.ts │ └── theme.ts ├── global.d.ts ├── models │ ├── account.ts │ ├── contact.ts │ └── index.ts ├── native │ └── MyButton.js ├── navigator │ ├── MainTab.tsx │ ├── MainTabBar.tsx │ └── index.tsx ├── pages │ ├── animate │ │ └── index.tsx │ ├── camera │ │ ├── index.tsx │ │ └── version-camera.tsx │ ├── category │ │ ├── data.json │ │ └── index.tsx │ ├── contact │ │ ├── List.tsx │ │ ├── data.tsx │ │ └── index.tsx │ ├── detail │ │ └── index.tsx │ ├── download │ │ └── index.tsx │ ├── fs │ │ └── index.tsx │ ├── h5 │ │ └── index.tsx │ ├── home │ │ └── index.tsx │ ├── login │ │ ├── index.tsx │ │ └── style.ts │ ├── me │ │ └── index.tsx │ └── table │ │ └── index.tsx ├── plugins │ ├── notification │ │ ├── Demo.jsx │ │ ├── NotifService.js │ │ └── NotificationHandler.js │ └── plugin-one │ │ └── .gitkeep ├── services │ ├── account.ts │ └── contact.ts ├── types │ ├── ResData.ts │ └── UserInfo.ts ├── utils │ ├── auth.ts │ ├── date.ts │ ├── env.ts │ ├── logger.ts │ ├── screen.ts │ ├── storage.ts │ └── uuid.ts └── wrappers │ └── .gitkeep ├── tsconfig.json └── yarn.lock /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | 35 | # node.js 36 | # 37 | node_modules/ 38 | npm-debug.log 39 | yarn-error.log 40 | 41 | # BUCK 42 | buck-out/ 43 | \.buckd/ 44 | # *.keystore 45 | # !debug.keystore 46 | 47 | # fastlane 48 | # 49 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 50 | # screenshots whenever they are needed. 51 | # For more information about the recommended setup visit: 52 | # https://docs.fastlane.tools/best-practices/source-control/ 53 | 54 | **/fastlane/report.xml 55 | **/fastlane/Preview.html 56 | **/fastlane/screenshots 57 | **/fastlane/test_output 58 | 59 | # Bundle artifact 60 | *.jsbundle 61 | 62 | # Ruby / CocoaPods 63 | /ios/Pods/ 64 | /vendor/bundle/ 65 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.5 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "iconfont", 4 | "Pressable", 5 | "RNFS", 6 | "todos", 7 | "wiiai's" 8 | ], 9 | "java.configuration.updateBuildConfiguration": "interactive", 10 | // 头部注释 11 | "fileheader.customMade": { 12 | "Author": "git config user.name", 13 | "LastEditors": "git config user.name", // 文件最后编辑者 与Author字段一致 14 | "Date": "Do not edit", // 文件创建时间(不变) 15 | "LastEditTime": "Do not edit", // 文件最后编辑时间 16 | "FilePath": "Do not edit", // 文件在项目中的相对路径 自动更新 17 | "Description": "" // 介绍文件的作用、文件的入参、出参。 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /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.5' 5 | 6 | gem 'cocoapods', '~> 1.11', '>= 1.11.2' 7 | -------------------------------------------------------------------------------- /__tests__/App-test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../01-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 | -------------------------------------------------------------------------------- /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.wowimrn", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.wowimrn", 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiai/react-native-template/b51f2be006437cfb699a99dabd41a727e50242f5/android/app/debug.keystore -------------------------------------------------------------------------------- /android/app/my-release-key.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wiiai/react-native-template/b51f2be006437cfb699a99dabd41a727e50242f5/android/app/my-release-key.keystore -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /android/app/src/debug/java/com/wowimrn/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.wowimrn; 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 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 64 | 65 | 66 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/wowimrn/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wowimrn; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.ReactRootView; 6 | import android.os.Bundle; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "WowImRN"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and 21 | * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer 22 | * (Paper). 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new MainActivityDelegate(this, getMainComponentName()); 27 | } 28 | 29 | public static class MainActivityDelegate extends ReactActivityDelegate { 30 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) { 31 | super(activity, mainComponentName); 32 | } 33 | 34 | @Override 35 | protected ReactRootView createRootView() { 36 | ReactRootView reactRootView = new ReactRootView(getContext()); 37 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 38 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED); 39 | return reactRootView; 40 | } 41 | 42 | @Override 43 | protected boolean isConcurrentRootEnabled() { 44 | // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18). 45 | // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html 46 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 47 | } 48 | 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) { 51 | super.onCreate(null); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/wowimrn/MainApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: GaoXiong 3 | * @LastEditors: GaoXiong 4 | * @Date: 2023-01-04 18:54:10 5 | * @LastEditTime: 2023-04-11 22:50:43 6 | * @FilePath: /react-native-template/android/app/src/main/java/com/wowimrn/MainApplication.java 7 | * @Description: 8 | */ 9 | package com.wowimrn; 10 | 11 | import android.app.Application; 12 | import android.content.Context; 13 | import com.facebook.react.PackageList; 14 | import com.facebook.react.ReactApplication; 15 | import com.facebook.react.ReactInstanceManager; 16 | import com.facebook.react.ReactNativeHost; 17 | import com.facebook.react.ReactPackage; 18 | import com.facebook.react.config.ReactFeatureFlags; 19 | import com.facebook.soloader.SoLoader; 20 | import com.wowimrn.newarchitecture.MainApplicationReactNativeHost; 21 | import java.lang.reflect.InvocationTargetException; 22 | import java.util.List; 23 | import com.rnfs.RNFSPackage; 24 | 25 | public class MainApplication extends Application implements ReactApplication { 26 | 27 | private final ReactNativeHost mReactNativeHost = 28 | new ReactNativeHost(this) { 29 | @Override 30 | public boolean getUseDeveloperSupport() { 31 | return BuildConfig.DEBUG; 32 | } 33 | 34 | @Override 35 | protected List getPackages() { 36 | @SuppressWarnings("UnnecessaryLocalVariable") 37 | List packages = new PackageList(this).getPackages(); 38 | 39 | // 不能自动注册的 package需要手动注册 40 | // Packages that cannot be autolinked yet can be added manually here, for example: 41 | packages.add(new RCTButtonPackage()); 42 | 43 | return packages; 44 | } 45 | 46 | @Override 47 | protected String getJSMainModuleName() { 48 | return "index"; 49 | } 50 | }; 51 | 52 | private final ReactNativeHost mNewArchitectureNativeHost = 53 | new MainApplicationReactNativeHost(this); 54 | 55 | @Override 56 | public ReactNativeHost getReactNativeHost() { 57 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 58 | return mNewArchitectureNativeHost; 59 | } else { 60 | return mReactNativeHost; 61 | } 62 | } 63 | 64 | @Override 65 | public void onCreate() { 66 | super.onCreate(); 67 | // If you opted-in for the New Architecture, we enable the TurboModule system 68 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 69 | SoLoader.init(this, /* native exopackage */ false); 70 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 71 | } 72 | 73 | /** 74 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 75 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 76 | * 77 | * @param context 78 | * @param reactInstanceManager 79 | */ 80 | private static void initializeFlipper( 81 | Context context, ReactInstanceManager reactInstanceManager) { 82 | if (BuildConfig.DEBUG) { 83 | try { 84 | /* 85 | We use reflection here to pick up the class that initializes Flipper, 86 | since Flipper library is not available in release mode 87 | */ 88 | Class aClass = Class.forName("com.wowimrn.ReactNativeFlipper"); 89 | aClass 90 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 91 | .invoke(null, context, reactInstanceManager); 92 | } catch (ClassNotFoundException e) { 93 | e.printStackTrace(); 94 | } catch (NoSuchMethodException e) { 95 | e.printStackTrace(); 96 | } catch (IllegalAccessException e) { 97 | e.printStackTrace(); 98 | } catch (InvocationTargetException e) { 99 | e.printStackTrace(); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/wowimrn/RCTButton.java: -------------------------------------------------------------------------------- 1 | package com.wowimrn; 2 | 3 | import android.view.View; 4 | import android.widget.Button; 5 | 6 | import com.facebook.react.bridge.Arguments; 7 | import com.facebook.react.bridge.WritableMap; 8 | import com.facebook.react.common.MapBuilder; 9 | import com.facebook.react.uimanager.SimpleViewManager; 10 | import com.facebook.react.uimanager.ThemedReactContext; 11 | import com.facebook.react.uimanager.annotations.ReactProp; 12 | import com.facebook.react.uimanager.events.RCTEventEmitter; 13 | 14 | import java.util.Map; 15 | 16 | import javax.annotation.Nullable; 17 | 18 | public class RCTButton extends SimpleViewManager 25 | 26 | 34 | 35 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /src/pages/camera/index.tsx: -------------------------------------------------------------------------------- 1 | import BPage from '@/baseUI/BPage'; 2 | import React, {Component} from 'react'; 3 | import { 4 | Alert, 5 | Animated, 6 | StyleSheet, 7 | Text, 8 | View, 9 | } from 'react-native'; 10 | import {RNCamera} from 'react-native-camera'; 11 | 12 | export class CameraScreen extends Component { 13 | constructor(props: any) { 14 | super(props); 15 | this.state = { 16 | moveAnim: new Animated.Value(0), 17 | }; 18 | } 19 | 20 | componentDidMount() { 21 | this.startAnimation(); 22 | } 23 | 24 | startAnimation = () => { 25 | this.state.moveAnim.setValue(0); 26 | Animated.timing(this.state.moveAnim, { 27 | toValue: -200, 28 | duration: 1500, 29 | useNativeDriver: false, 30 | }).start(() => this.startAnimation()); 31 | }; 32 | 33 | // 识别二维码 34 | onBarCodeRead = (result: any) => { 35 | Alert.alert(result.data) 36 | }; 37 | 38 | render() { 39 | return ( 40 | 41 | { 43 | (this as any).camera = ref; 44 | }} 45 | style={styles.preview} 46 | type={RNCamera.Constants.Type.back} 47 | flashMode={RNCamera.Constants.FlashMode.on} 48 | onBarCodeRead={this.onBarCodeRead}> 49 | 50 | 51 | 57 | 58 | 将二维码放入框内,即可自动扫描 59 | 60 | 61 | 62 | 63 | ); 64 | } 65 | } 66 | 67 | const styles = StyleSheet.create({ 68 | container: { 69 | flex: 1, 70 | // flexDirection: 'row' 71 | }, 72 | preview: { 73 | flex: 1, 74 | justifyContent: 'flex-end', 75 | alignItems: 'center', 76 | }, 77 | rectangleContainer: { 78 | flex: 1, 79 | alignItems: 'center', 80 | justifyContent: 'center', 81 | backgroundColor: 'transparent', 82 | }, 83 | rectangle: { 84 | height: 200, 85 | width: 200, 86 | borderWidth: 1, 87 | borderColor: '#00FF00', 88 | backgroundColor: 'transparent', 89 | }, 90 | rectangleText: { 91 | flex: 0, 92 | color: '#fff', 93 | marginTop: 10, 94 | }, 95 | border: { 96 | flex: 0, 97 | width: 200, 98 | height: 2, 99 | backgroundColor: '#00FF00', 100 | }, 101 | }); -------------------------------------------------------------------------------- /src/pages/camera/version-camera.tsx: -------------------------------------------------------------------------------- 1 | // /* 2 | // * @Author: GaoXiong 3 | // * @LastEditors: GaoXiong 4 | // * @Date: 2023-04-11 23:45:41 5 | // * @LastEditTime: 2023-04-12 01:04:28 6 | // * @FilePath: /react-native-template/src/pages/camera/index.tsx 7 | // * @Description: 8 | // */ 9 | // // /* 10 | // // * @Author: GaoXiong 11 | // // * @LastEditors: GaoXiong 12 | // // * @Date: 2023-04-11 23:45:41 13 | // // * @LastEditTime: 2023-04-11 23:50:47 14 | // // * @FilePath: /react-native-template/src/pages/camera/index.tsx 15 | // // * @Description: 16 | // // */ 17 | // import React, {useEffect, useState} from 'react'; 18 | // import {Animated, StyleSheet, Text, View} from 'react-native'; 19 | // import {useCameraDevices, Camera} from 'react-native-vision-camera'; 20 | // import {useScanBarcodes, BarcodeFormat} from 'vision-camera-code-scanner'; 21 | // import BPage from '@/baseUI/BPage'; 22 | 23 | import { Text, View } from "react-native" 24 | 25 | // export function CameraScreen() { 26 | // const [hasMicrophonePermission, setHasMicrophonePermission] = useState(false); 27 | // const [hasCameraPermission, setHasCameraPermission] = useState(false); 28 | 29 | // const devices = useCameraDevices(); 30 | // const device = devices.back; 31 | 32 | // const [frameProcessor, barcodes] = useScanBarcodes( 33 | // [BarcodeFormat.ALL_FORMATS], 34 | // {checkInverted: true}, 35 | // ); 36 | 37 | // const request = async () => { 38 | // const cameraPermission = await Camera.requestCameraPermission(); 39 | // console.log(cameraPermission); 40 | // // setHasCameraPermission(cameraPermission == 'authorized'); 41 | // }; 42 | 43 | // React.useEffect(() => { 44 | // console.log(barcodes); 45 | // }, [barcodes]); 46 | 47 | // useEffect(() => { 48 | // request(); 49 | // // Camera.getCameraPermissionStatus().then((status) => setHasCameraPermission(status === 'authorized')) 50 | // // Camera.getMicrophonePermissionStatus().then((status) => setHasMicrophonePermission(status === 'authorized')); 51 | // }, []); 52 | 53 | // if (device == null) return LOADING...; 54 | 55 | // return ( 56 | // 57 | // {barcodes.map((barcode, idx) => ( 58 | // 59 | // {barcode.displayValue} 60 | // 61 | // ))} 62 | // 63 | // 72 | // 73 | // 74 | // ); 75 | // } 76 | 77 | // const styles = StyleSheet.create({ 78 | // barcodeTextURL: { 79 | // fontSize: 20, 80 | // color: 'white', 81 | // fontWeight: 'bold', 82 | // }, 83 | // }); 84 | 85 | 86 | export const CameraScreen = () => { 87 | return ( 88 | 89 | Hello 90 | 91 | ) 92 | } -------------------------------------------------------------------------------- /src/pages/category/index.tsx: -------------------------------------------------------------------------------- 1 | import {ScrollView, StyleSheet, View} from 'react-native'; 2 | import data from './data.json'; 3 | import { 4 | TouchableHighlight, 5 | TouchableWithoutFeedback, 6 | } from 'react-native-gesture-handler'; 7 | import BPage from '@/baseUI/BPage'; 8 | import {useEffect, useState} from 'react'; 9 | import {Center, Flex, HStack, Image, Text} from 'native-base'; 10 | 11 | const CategoryScreen = () => { 12 | const treeData = data.data.list; 13 | const [current, setCurrent] = useState(undefined); 14 | 15 | useEffect(() => { 16 | setCurrent(treeData[0].id); 17 | }, []); 18 | 19 | const renderMenu = () => { 20 | return treeData.map(it => { 21 | const stl = 22 | current === it.id 23 | ? { 24 | borderRightWidth: 3, 25 | borderRightColor: 'blue', 26 | borderStyle: 'solid' as const, 27 | backgroundColor: '#fff', 28 | } 29 | : { 30 | borderRightWidth: 3, 31 | borderRightColor: 'transparent', 32 | borderStyle: 'solid' as const, 33 | }; 34 | return ( 35 | { 38 | setCurrent(it.id); 39 | }}> 40 | 41 | 48 | {it.title} 49 | 50 | 51 | 52 | ); 53 | }); 54 | }; 55 | 56 | const renderList = () => { 57 | const list = treeData.find(it => it.id === current)?.children || []; 58 | if (!list.length) { 59 | return null; 60 | } 61 | const children = list.map((it, index) => { 62 | return ( 63 | 64 | 72 | 74 | 75 | {it.title} 76 | 77 | 78 | 79 | ); 80 | }); 81 | 82 | return ( 83 | 84 | 85 | 91 | 92 | 93 | 课程分类 94 | 95 | 96 | {children} 97 | 98 | 99 | ); 100 | }; 101 | 102 | return ( 103 | 104 | 105 | 106 | 107 | {renderMenu()} 108 | 109 | 110 | 111 | 119 | {renderList()} 120 | 121 | 122 | 123 | 124 | ); 125 | }; 126 | 127 | const styles = StyleSheet.create({ 128 | contentContainer: {}, 129 | }); 130 | 131 | export default CategoryScreen; -------------------------------------------------------------------------------- /src/pages/contact/List.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect, useRef} from 'react'; 2 | import {View, Text, StyleSheet, Animated, Easing} from 'react-native'; 3 | import {BList, getSimpleFooterLoading} from '@/baseUI/BList'; 4 | 5 | const styles = StyleSheet.create({ 6 | row: { 7 | height: 50, 8 | justifyContent: 'center', 9 | padding: 10, 10 | marginHorizontal: 10, 11 | borderBottomWidth: 6, 12 | borderBottomColor: '#eee', 13 | backgroundColor: 'white', 14 | }, 15 | rowTitle: { 16 | fontSize: 16, 17 | fontWeight: 'bold', 18 | }, 19 | }); 20 | 21 | export function FruitList() { 22 | const [data, setData] = useState([] as string[]); 23 | const [finished, setFinished] = useState(false); 24 | 25 | return ( 26 | 27 | 28 | footerLoading={getSimpleFooterLoading} 29 | dataSource={data} 30 | disableLoadMore={finished} 31 | renderItem={({item}) => { 32 | return ( 33 | 34 | {item} 35 | 36 | ); 37 | }} 38 | onRefresh={callback => { 39 | console.log(`onRefresh`) 40 | const list = (new Array(20)).fill(undefined).map((_, i) => { 41 | return `${i}`; 42 | }) 43 | setTimeout(() => { 44 | setFinished(false) 45 | setData(list) 46 | callback(); 47 | }, 2000); 48 | }} 49 | onLoad={callback => { 50 | console.log(`onLoad`) 51 | const list = (new Array(20)).fill(undefined).map((_, i) => { 52 | return `${data.length + i}`; 53 | }) 54 | setTimeout(() => { 55 | const newList = [...data, ...list]; 56 | if (newList.length > 50) { 57 | setFinished(true) 58 | } 59 | setData(newList) 60 | callback(); 61 | }, 2000); 62 | }} 63 | /> 64 | 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /src/pages/contact/data.tsx: -------------------------------------------------------------------------------- 1 | export const data = [ 2 | { 3 | id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', 4 | fullName: 'Aafreen Khan', 5 | timeStamp: '12:47 PM', 6 | recentText: 'Good Day!', 7 | avatarUrl: 8 | 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500', 9 | }, 10 | { 11 | id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', 12 | fullName: 'Sujitha Mathur', 13 | timeStamp: '11:11 PM', 14 | recentText: 'Cheer up, there!', 15 | avatarUrl: 16 | 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTyEaZqT3fHeNrPGcnjLLX1v_W4mvBlgpwxnA&usqp=CAU', 17 | }, 18 | { 19 | id: '58694a0f-3da1-471f-bd96-145571e29d72', 20 | fullName: 'Anci Barroco', 21 | timeStamp: '6:22 PM', 22 | recentText: 'Good Day!', 23 | avatarUrl: 'https://miro.medium.com/max/1400/0*0fClPmIScV5pTLoE.jpg', 24 | }, 25 | { 26 | id: '68694a0f-3da1-431f-bd56-142371e29d72', 27 | fullName: 'Aniket Kumar', 28 | timeStamp: '8:56 PM', 29 | recentText: 'All the best', 30 | avatarUrl: 31 | 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSr01zI37DYuR8bMV5exWQBSw28C1v_71CAh8d7GP1mplcmTgQA6Q66Oo--QedAN1B4E1k&usqp=CAU', 32 | }, 33 | { 34 | id: '28694a0f-3da1-471f-bd96-142456e29d72', 35 | fullName: 'Kiara', 36 | timeStamp: '12:47 PM', 37 | recentText: 'I will call today.', 38 | avatarUrl: 39 | 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBwgu1A5zgPSvfE83nurkuzNEoXs9DMNr8Ww&usqp=CAU', 40 | }, 41 | ]; 42 | -------------------------------------------------------------------------------- /src/pages/contact/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {Text, View} from 'react-native'; 3 | import BPage from '@/baseUI/BPage'; 4 | import {RefreshControl} from 'react-native'; 5 | import { 6 | Box, 7 | Heading, 8 | HStack, 9 | FlatList, 10 | Avatar, 11 | VStack, 12 | Button, 13 | } from 'native-base'; 14 | import {useStore} from '@/models'; 15 | import {observer} from 'mobx-react-lite'; 16 | import LottieView from 'lottie-react-native'; 17 | const fruitsAnimation = require('@/assets/animation/bounce-fruit.json'); 18 | 19 | import {FruitList} from './List'; 20 | 21 | export const ContactScreen = FruitList 22 | 23 | export const ContactScreen1 = observer(() => { 24 | const store = useStore(); 25 | const [loading, setLoading] = React.useState(false); 26 | const lottieViewRef = React.useRef(null); 27 | 28 | const fetchList = () => { 29 | setLoading(true); 30 | lottieViewRef.current?.play(); 31 | store.contactStore.fetchContacts().then(() => { 32 | console.log(store.contactStore.list); 33 | setTimeout(() => { 34 | setLoading(false); 35 | lottieViewRef.current?.pause(); 36 | lottieViewRef.current?.reset(); 37 | }, 2000); 38 | }); 39 | }; 40 | 41 | React.useEffect(() => { 42 | fetchList(); 43 | }, []); 44 | 45 | const refreshControl = ( 46 | 54 | ); 55 | 56 | return ( 57 | 58 | 59 | 60 | 联系人 ({store.contactStore.list.length}) 61 | 62 | 63 | 71 | 77 | 78 | ( 83 | 89 | 94 | 95 | 96 | 97 | 98 | {item.nickname} 99 | 100 | 101 | 102 | 109 | 110 | 111 | )} 112 | /> 113 | 114 | 115 | 116 | ); 117 | }); 118 | -------------------------------------------------------------------------------- /src/pages/detail/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {Text, View} from 'react-native'; 3 | import BPage from '@/baseUI/BPage'; 4 | 5 | export function DetailScreen() { 6 | return ( 7 | 8 | 9 | Detail 10 | 11 | 12 | ); 13 | } -------------------------------------------------------------------------------- /src/pages/download/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {Image, Text} from 'react-native'; 3 | import {observer} from 'mobx-react-lite'; 4 | import BPage from '@/baseUI/BPage'; 5 | import {Button, View} from 'native-base'; 6 | import RNFS from 'react-native-fs'; 7 | import Video from 'react-native-video'; 8 | 9 | const ImageDemo = () => { 10 | const [path, setPath] = React.useState(''); 11 | 12 | const download = async () => { 13 | const path = RNFS.DocumentDirectoryPath + '/demo.jpeg'; 14 | const res = RNFS.downloadFile({ 15 | fromUrl: 'http://s3.airtlab.com/a5.jpeg', 16 | toFile: path, 17 | }); 18 | const data = await res.promise; 19 | console.log(`write res`, data); 20 | console.log(`path: ${path}`); 21 | setPath(path); 22 | }; 23 | 24 | return ( 25 | 26 | 27 | 30 | {path} 31 | {path ? ( 32 | 33 | ) : null} 34 | 35 | 36 | ); 37 | }; 38 | 39 | const VideoDemo = () => { 40 | const [path, setPath] = React.useState(''); 41 | const download = async () => { 42 | const path = RNFS.DocumentDirectoryPath + '/movie.mp4'; 43 | const res = RNFS.downloadFile({ 44 | fromUrl: 'https://www.runoob.com/try/demo_source/movie.mp4', 45 | toFile: path, 46 | begin: (res) => { 47 | // 开始下载时回调 48 | console.log('begin', Math.floor(Date.now() / 1000), res); 49 | }, 50 | progress: (res) => { 51 | // 下载过程中回调,根据 options 中设置progressDivider:5,则在完成5%,10%,15%,...,100%时分别回调一次,共回调20次。 52 | console.log('progress', Math.floor(Date.now() / 1000), res); 53 | } 54 | }); 55 | const data = await res.promise; 56 | console.log(`write res`, data); 57 | console.log(`path: ${path}`); 58 | setPath(path); 59 | }; 60 | 61 | const render = () => { 62 | if (!path) { 63 | return null; 64 | } 65 | return ( 66 |