├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── .vscode └── settings.json ├── App.tsx ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── shopzy │ │ │ └── app │ │ │ └── ReactNativeFlipper.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── shopzy │ │ │ │ └── app │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-mdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xxhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xxxhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable │ │ │ ├── rn_edit_text_material.xml │ │ │ └── splashscreen.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-night │ │ │ └── colors.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── release │ │ └── java │ │ └── com │ │ └── shopzy │ │ └── app │ │ └── ReactNativeFlipper.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── app.json ├── assets ├── fonts │ ├── Manrope-Bold.ttf │ ├── Manrope-Medium.ttf │ ├── Manrope-Regular.ttf │ ├── Manrope-SemiBold.ttf │ └── index.ts ├── images │ ├── NoNetwork.png │ ├── ProductFallbackImage.png │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png └── svg │ ├── Arrow.svg │ ├── Cart.svg │ ├── Category.svg │ ├── DoneIcon.svg │ ├── Heart.svg │ ├── Home.svg │ ├── LikeIcon.svg │ ├── PlusIcon.svg │ ├── SearchIcon.svg │ ├── ThreeDotsVertical.svg │ └── index.ts ├── babel.config.js ├── ios ├── .gitignore ├── .xcode.env ├── Podfile ├── Podfile.lock ├── Podfile.properties.json ├── Shopzy.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── Shopzy.xcscheme ├── Shopzy.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Shopzy │ ├── AppDelegate.h │ ├── AppDelegate.mm │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── App-Icon-1024x1024@1x.png │ │ └── Contents.json │ ├── Contents.json │ ├── SplashScreen.imageset │ │ ├── Contents.json │ │ └── image.png │ └── SplashScreenBackground.imageset │ │ ├── Contents.json │ │ └── image.png │ ├── Info.plist │ ├── Shopzy-Bridging-Header.h │ ├── Shopzy.entitlements │ ├── SplashScreen.storyboard │ ├── Supporting │ └── Expo.plist │ ├── main.m │ └── noop-file.swift ├── metro.config.js ├── package.json ├── src ├── components │ ├── AppButton.tsx │ ├── AppText.tsx │ ├── CartButtonWithIndicator.tsx │ ├── CartProductQuantitySelector.tsx │ ├── DropdownSelector.tsx │ ├── HorizontalBannerList.tsx │ ├── ImageCarousel.tsx │ ├── ProductCard.tsx │ ├── ProductGridList.tsx │ ├── QuickActionButton.tsx │ ├── Spacer.tsx │ ├── StarRatingViewer.tsx │ └── index.ts ├── constants │ └── index.ts ├── containers │ ├── FlexContainer.tsx │ ├── MainContainer.tsx │ ├── PaddingContainer.tsx │ └── index.ts ├── declaration.d.ts ├── navigation │ └── BottomNavBar.tsx ├── screens │ ├── Cart.tsx │ ├── Categories.tsx │ ├── Favorites.tsx │ ├── Home.tsx │ ├── More.tsx │ ├── ProductDetails.tsx │ └── index.ts ├── store │ └── index.ts ├── types │ └── index.ts └── utils │ ├── functions.ts │ └── index.ts ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | settings: { 8 | react: { 9 | version: "detect", 10 | }, 11 | }, 12 | extends: [ 13 | "eslint:recommended", 14 | "plugin:react/recommended", 15 | "plugin:@typescript-eslint/recommended", 16 | ], 17 | overrides: [], 18 | parser: "@typescript-eslint/parser", 19 | parserOptions: { 20 | ecmaVersion: "latest", 21 | sourceType: "module", 22 | }, 23 | plugins: ["react", "@typescript-eslint", "react-native"], 24 | rules: { 25 | "react-native/no-unused-styles": 1, 26 | "react/no-unescaped-entities": 0, 27 | "react/jsx-no-useless-fragment": 2, 28 | "@typescript-eslint/no-explicit-any": 2, 29 | "react-native/split-platform-components": 2, 30 | "react-native/no-inline-styles": 0, 31 | "react-native/no-color-literals": 0, 32 | "react-native/no-raw-text": 0, 33 | "react/prop-types": 0, 34 | "no-use-before-define": 0, 35 | "react/display-name": 0, 36 | "no-unreachable": 2, 37 | "dot-notation": 1, 38 | "no-console": [1, { allow: ["error"] }], 39 | "no-useless-return": 1, 40 | "no-else-return": 1, 41 | "import/order": 0, 42 | "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 43 | "react-native/sort-styles": 0, 44 | "react/react-in-jsx-scope": 0, 45 | "react/jsx-uses-react": 0, 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | 4 | # Expo 5 | .expo/ 6 | dist/ 7 | web-build/ 8 | 9 | # Native 10 | *.orig.* 11 | *.jks 12 | *.p8 13 | *.p12 14 | *.key 15 | *.mobileprovision 16 | 17 | # Metro 18 | .metro-health-check* 19 | 20 | # debug 21 | npm-debug.* 22 | yarn-debug.* 23 | yarn-error.* 24 | 25 | # macOS 26 | .DS_Store 27 | *.pem 28 | 29 | # local env files 30 | .env*.local 31 | 32 | # typescript 33 | *.tsbuildinfo 34 | .tamagui/tamagui.config.json 35 | 36 | 37 | # Android Studio generated files and folders 38 | captures/ 39 | .externalNativeBuild/ 40 | .cxx/ 41 | *.apk 42 | *.aab 43 | output-metadata.json 44 | 45 | # Gradle files 46 | .gradle/ 47 | build/ 48 | 49 | # Keystore files 50 | *.jks 51 | *.keystore 52 | 53 | # Log/OS Files 54 | *.log 55 | 56 | # Android Profiling 57 | *.hprof 58 | 59 | # Local configuration file (sdk path, etc) 60 | local.properties -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSameLine": true, 4 | "bracketSpacing": false, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "tabWidth": 2, 8 | "semi": true, 9 | "printWidth": 80 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["bson", "Kanat", "netinfo", "Rahul", "Shopzy"] 3 | } 4 | -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import BottomNavBar from '@app/navigation/BottomNavBar'; 2 | import {CartScreen, ProductDetailsScreen} from '@app/screens'; 3 | import {AppScreensParamsList} from '@app/types'; 4 | import {AppColors} from '@app/utils'; 5 | import { 6 | ManropeBold, 7 | ManropeMedium, 8 | ManropeRegular, 9 | ManropeSemiBold, 10 | } from '@assets/fonts'; 11 | import {NavigationContainer} from '@react-navigation/native'; 12 | import { 13 | NativeStackNavigationOptions, 14 | createNativeStackNavigator, 15 | } from '@react-navigation/native-stack'; 16 | import {useFonts} from 'expo-font'; 17 | import React from 'react'; 18 | import Toast from 'react-native-toast-message'; 19 | 20 | function App(): JSX.Element | null { 21 | const Stack = createNativeStackNavigator(); 22 | 23 | const [fontsLoaded] = useFonts({ 24 | ManropeRegular, 25 | ManropeMedium, 26 | ManropeSemiBold, 27 | ManropeBold, 28 | }); 29 | 30 | if (!fontsLoaded) { 31 | return null; 32 | } 33 | 34 | const screensOptions: NativeStackNavigationOptions = { 35 | headerShown: false, 36 | orientation: 'portrait', 37 | contentStyle: { 38 | backgroundColor: AppColors.PureWhite, 39 | }, 40 | animation: 'slide_from_right', 41 | }; 42 | 43 | return ( 44 | 45 | 46 | 51 | 56 | 61 | 62 | 63 | 64 | ); 65 | } 66 | 67 | export default App; 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shopzy Mobile App 2 | 3 | # App Screenshots 4 |

5 | Home 6 | Product Details 7 | Fav 8 | Cart 9 |

10 | 11 | ### Technical Details 12 | 13 | - This app has been bootstrapped with Expo TypeScript (https://expo.dev) 14 | 15 | # Run this app (development): 16 | 17 | - Clone the repo HTTPS: 18 | 19 | ``` 20 | git clone https://github.com/zxcodes/Shopzy.git 21 | 22 | ``` 23 | 24 | - Clone Over SSH: 25 | 26 | ``` 27 | git clone git@github.com:zxcodes/Shopzy.git 28 | ``` 29 | 30 | ## Install dependencies 31 | 32 | ``` 33 | cd Shopzy && yarn install 34 | ``` 35 | 36 | ## To install any expo dependency use yarn package manager: 37 | 38 | - Example (add --yarn flag at the end to force yarn usage): 39 | 40 | ``` 41 | npx expo install expo-av --yarn 42 | ``` 43 | 44 | ## Running on a simulator (or) emulator: 45 | 46 | - Start the development server after installing dependencies via `yarn install` 47 | 48 | ``` 49 | yarn run ios || yarn run android 50 | ``` 51 | 52 | ## Running on a physical device: 53 | 54 | - Start the development server after installing dependencies via `yarn install` 55 | 56 | ``` 57 | yarn start 58 | ``` 59 | 60 | - Download the Expo Go App and scan the QR Code from the terminal. On iOS, scan the QR Code from the inbuilt scanner or the native Camera App. 61 | 62 | - Expo Go Android App: https://play.google.com/store/apps/details?id=host.exp.exponent 63 | 64 | - Expo Go iOS App: https://apps.apple.com/us/app/expo-go/id982107779 65 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Android/IntelliJ 6 | # 7 | build/ 8 | .idea 9 | .gradle 10 | local.properties 11 | *.iml 12 | *.hprof 13 | 14 | # Bundle artifacts 15 | *.jsbundle 16 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "com.facebook.react" 3 | 4 | def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() 5 | 6 | /** 7 | * This is the configuration block to customize your React Native Android app. 8 | * By default you don't need to apply any configuration, just uncomment the lines you need. 9 | */ 10 | react { 11 | entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim()) 12 | reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() 13 | hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc" 14 | codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() 15 | 16 | // Use Expo CLI to bundle the app, this ensures the Metro config 17 | // works correctly with Expo projects. 18 | cliFile = new File(["node", "--print", "require.resolve('@expo/cli')"].execute(null, rootDir).text.trim()) 19 | bundleCommand = "export:embed" 20 | 21 | /* Folders */ 22 | // The root of your project, i.e. where "package.json" lives. Default is '..' 23 | // root = file("../") 24 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 25 | // reactNativeDir = file("../node_modules/react-native") 26 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen 27 | // codegenDir = file("../node_modules/@react-native/codegen") 28 | 29 | /* Variants */ 30 | // The list of variants to that are debuggable. For those we're going to 31 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 32 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 33 | // debuggableVariants = ["liteDebug", "prodDebug"] 34 | 35 | /* Bundling */ 36 | // A list containing the node command and its flags. Default is just 'node'. 37 | // nodeExecutableAndArgs = ["node"] 38 | 39 | // 40 | // The path to the CLI configuration file. Default is empty. 41 | // bundleConfig = file(../rn-cli.config.js) 42 | // 43 | // The name of the generated asset file containing your JS bundle 44 | // bundleAssetName = "MyApplication.android.bundle" 45 | // 46 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 47 | // entryFile = file("../js/MyApplication.android.js") 48 | // 49 | // A list of extra flags to pass to the 'bundle' commands. 50 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 51 | // extraPackagerArgs = [] 52 | 53 | /* Hermes Commands */ 54 | // The hermes compiler command to run. By default it is 'hermesc' 55 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 56 | // 57 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 58 | // hermesFlags = ["-O", "-output-source-map"] 59 | } 60 | 61 | /** 62 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 63 | */ 64 | def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean() 65 | 66 | /** 67 | * The preferred build flavor of JavaScriptCore (JSC) 68 | * 69 | * For example, to use the international variant, you can use: 70 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 71 | * 72 | * The international variant includes ICU i18n library and necessary data 73 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 74 | * give correct results when using with locales other than en-US. Note that 75 | * this variant is about 6MiB larger per architecture than default. 76 | */ 77 | def jscFlavor = 'org.webkit:android-jsc:+' 78 | 79 | android { 80 | ndkVersion rootProject.ext.ndkVersion 81 | 82 | compileSdkVersion rootProject.ext.compileSdkVersion 83 | 84 | namespace 'com.shopzy.app' 85 | defaultConfig { 86 | applicationId 'com.shopzy.app' 87 | minSdkVersion rootProject.ext.minSdkVersion 88 | targetSdkVersion rootProject.ext.targetSdkVersion 89 | versionCode 1 90 | versionName "1.0.0" 91 | 92 | buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString()) 93 | } 94 | signingConfigs { 95 | debug { 96 | storeFile file('debug.keystore') 97 | storePassword 'android' 98 | keyAlias 'androiddebugkey' 99 | keyPassword 'android' 100 | } 101 | } 102 | buildTypes { 103 | debug { 104 | signingConfig signingConfigs.debug 105 | } 106 | release { 107 | // Caution! In production, you need to generate your own keystore file. 108 | // see https://reactnative.dev/docs/signed-apk-android. 109 | signingConfig signingConfigs.debug 110 | shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false) 111 | minifyEnabled enableProguardInReleaseBuilds 112 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 113 | } 114 | } 115 | } 116 | 117 | // Apply static values from `gradle.properties` to the `android.packagingOptions` 118 | // Accepts values in comma delimited lists, example: 119 | // android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini 120 | ["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop -> 121 | // Split option: 'foo,bar' -> ['foo', 'bar'] 122 | def options = (findProperty("android.packagingOptions.$prop") ?: "").split(","); 123 | // Trim all elements in place. 124 | for (i in 0.. 0) { 129 | println "android.packagingOptions.$prop += $options ($options.length)" 130 | // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**' 131 | options.each { 132 | android.packagingOptions[prop] += it 133 | } 134 | } 135 | } 136 | 137 | dependencies { 138 | // The version of react-native is set by the React Native Gradle Plugin 139 | implementation("com.facebook.react:react-android") 140 | 141 | def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true"; 142 | def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true"; 143 | def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true"; 144 | def frescoVersion = rootProject.ext.frescoVersion 145 | 146 | // If your app supports Android versions before Ice Cream Sandwich (API level 14) 147 | if (isGifEnabled || isWebpEnabled) { 148 | implementation("com.facebook.fresco:fresco:${frescoVersion}") 149 | implementation("com.facebook.fresco:imagepipeline-okhttp3:${frescoVersion}") 150 | } 151 | 152 | if (isGifEnabled) { 153 | // For animated gif support 154 | implementation("com.facebook.fresco:animated-gif:${frescoVersion}") 155 | } 156 | 157 | if (isWebpEnabled) { 158 | // For webp support 159 | implementation("com.facebook.fresco:webpsupport:${frescoVersion}") 160 | if (isWebpAnimatedEnabled) { 161 | // Animated webp support 162 | implementation("com.facebook.fresco:animated-webp:${frescoVersion}") 163 | } 164 | } 165 | 166 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") 167 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 168 | exclude group:'com.squareup.okhttp3', module:'okhttp' 169 | } 170 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") 171 | 172 | if (hermesEnabled.toBoolean()) { 173 | implementation("com.facebook.react:hermes-android") 174 | } else { 175 | implementation jscFlavor 176 | } 177 | } 178 | 179 | apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle"); 180 | applyNativeModulesAppBuildGradle(project) 181 | -------------------------------------------------------------------------------- /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 | # react-native-reanimated 11 | -keep class com.swmansion.reanimated.** { *; } 12 | -keep class com.facebook.react.turbomodule.** { *; } 13 | 14 | # Add any project specific keep options here: 15 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/debug/java/com/shopzy/app/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.shopzy.app; 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.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceEventListener; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | /** 28 | * Class responsible of loading Flipper inside your React Native application. This is the debug 29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup. 30 | */ 31 | public class ReactNativeFlipper { 32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 33 | if (FlipperUtils.shouldEnableFlipper(context)) { 34 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 35 | 36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 37 | client.addPlugin(new DatabasesFlipperPlugin(context)); 38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 39 | client.addPlugin(CrashReporterPlugin.getInstance()); 40 | 41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 42 | NetworkingModule.setCustomClientBuilder( 43 | new NetworkingModule.CustomClientBuilder() { 44 | @Override 45 | public void apply(OkHttpClient.Builder builder) { 46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 47 | } 48 | }); 49 | client.addPlugin(networkFlipperPlugin); 50 | client.start(); 51 | 52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 53 | // Hence we run if after all native modules have been initialized 54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 55 | if (reactContext == null) { 56 | reactInstanceManager.addReactInstanceEventListener( 57 | new ReactInstanceEventListener() { 58 | @Override 59 | public void onReactContextInitialized(ReactContext reactContext) { 60 | reactInstanceManager.removeReactInstanceEventListener(this); 61 | reactContext.runOnNativeModulesQueueThread( 62 | new Runnable() { 63 | @Override 64 | public void run() { 65 | client.addPlugin(new FrescoFlipperPlugin()); 66 | } 67 | }); 68 | } 69 | }); 70 | } else { 71 | client.addPlugin(new FrescoFlipperPlugin()); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/shopzy/app/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.shopzy.app; 2 | 3 | import android.os.Build; 4 | import android.os.Bundle; 5 | 6 | import com.facebook.react.ReactActivity; 7 | import com.facebook.react.ReactActivityDelegate; 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 9 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 10 | 11 | import expo.modules.ReactActivityDelegateWrapper; 12 | 13 | public class MainActivity extends ReactActivity { 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | // Set the theme to AppTheme BEFORE onCreate to support 17 | // coloring the background, status bar, and navigation bar. 18 | // This is required for expo-splash-screen. 19 | setTheme(R.style.AppTheme); 20 | super.onCreate(null); 21 | } 22 | 23 | /** 24 | * Returns the name of the main component registered from JavaScript. 25 | * This is used to schedule rendering of the component. 26 | */ 27 | @Override 28 | protected String getMainComponentName() { 29 | return "main"; 30 | } 31 | 32 | /** 33 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 34 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 35 | * (aka React 18) with two boolean flags. 36 | */ 37 | @Override 38 | protected ReactActivityDelegate createReactActivityDelegate() { 39 | return new ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, new DefaultReactActivityDelegate( 40 | this, 41 | getMainComponentName(), 42 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 43 | DefaultNewArchitectureEntryPoint.getFabricEnabled())); 44 | } 45 | 46 | /** 47 | * Align the back button behavior with Android S 48 | * where moving root activities to background instead of finishing activities. 49 | * @see onBackPressed 50 | */ 51 | @Override 52 | public void invokeDefaultOnBackPressed() { 53 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { 54 | if (!moveTaskToBack(false)) { 55 | // For non-root activities, use the default implementation to finish them. 56 | super.invokeDefaultOnBackPressed(); 57 | } 58 | return; 59 | } 60 | 61 | // Use the default back button implementation on Android S 62 | // because it's doing more than {@link Activity#moveTaskToBack} in fact. 63 | super.invokeDefaultOnBackPressed(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/shopzy/app/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.shopzy.app; 2 | 3 | import android.app.Application; 4 | import android.content.res.Configuration; 5 | import androidx.annotation.NonNull; 6 | 7 | import com.facebook.react.PackageList; 8 | import com.facebook.react.ReactApplication; 9 | import com.facebook.react.ReactNativeHost; 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.config.ReactFeatureFlags; 12 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 13 | import com.facebook.react.defaults.DefaultReactNativeHost; 14 | import com.facebook.soloader.SoLoader; 15 | 16 | import expo.modules.ApplicationLifecycleDispatcher; 17 | import expo.modules.ReactNativeHostWrapper; 18 | 19 | import java.util.List; 20 | 21 | public class MainApplication extends Application implements ReactApplication { 22 | 23 | private final ReactNativeHost mReactNativeHost = 24 | new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) { 25 | @Override 26 | public boolean getUseDeveloperSupport() { 27 | return BuildConfig.DEBUG; 28 | } 29 | 30 | @Override 31 | protected List getPackages() { 32 | @SuppressWarnings("UnnecessaryLocalVariable") 33 | List packages = new PackageList(this).getPackages(); 34 | // Packages that cannot be autolinked yet can be added manually here, for example: 35 | // packages.add(new MyReactNativePackage()); 36 | return packages; 37 | } 38 | 39 | @Override 40 | protected String getJSMainModuleName() { 41 | return ".expo/.virtual-metro-entry"; 42 | } 43 | 44 | @Override 45 | protected boolean isNewArchEnabled() { 46 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 47 | } 48 | 49 | @Override 50 | protected Boolean isHermesEnabled() { 51 | return BuildConfig.IS_HERMES_ENABLED; 52 | } 53 | }); 54 | 55 | @Override 56 | public ReactNativeHost getReactNativeHost() { 57 | return mReactNativeHost; 58 | } 59 | 60 | @Override 61 | public void onCreate() { 62 | super.onCreate(); 63 | SoLoader.init(this, /* native exopackage */ false); 64 | if (!BuildConfig.REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS) { 65 | ReactFeatureFlags.unstable_useRuntimeSchedulerAlways = false; 66 | } 67 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 68 | // If you opted-in for the New Architecture, we load the native entry point for this app. 69 | DefaultNewArchitectureEntryPoint.load(); 70 | } 71 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 72 | ApplicationLifecycleDispatcher.onApplicationCreate(this); 73 | } 74 | 75 | @Override 76 | public void onConfigurationChanged(@NonNull Configuration newConfig) { 77 | super.onConfigurationChanged(newConfig); 78 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/drawable-hdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/drawable-mdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff 3 | #ffffff 4 | #023c69 5 | #ffffff 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Shopzy 3 | contain 4 | false 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 17 | -------------------------------------------------------------------------------- /android/app/src/release/java/com/shopzy/app/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.shopzy.app; 8 | 9 | import android.content.Context; 10 | import com.facebook.react.ReactInstanceManager; 11 | 12 | /** 13 | * Class responsible of loading Flipper inside your React Native application. This is the release 14 | * flavor of it so it's empty as we don't want to load Flipper. 15 | */ 16 | public class ReactNativeFlipper { 17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 18 | // Do nothing as we don't want to initialize Flipper on Release. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = findProperty('android.buildToolsVersion') ?: '33.0.0' 6 | minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '21') 7 | compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '33') 8 | targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '33') 9 | kotlinVersion = findProperty('android.kotlinVersion') ?: '1.8.10' 10 | frescoVersion = findProperty('expo.frescoVersion') ?: '2.5.0' 11 | 12 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. 13 | ndkVersion = "23.1.7779620" 14 | } 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | dependencies { 20 | classpath('com.android.tools.build:gradle:7.4.2') 21 | classpath('com.facebook.react:react-native-gradle-plugin') 22 | } 23 | } 24 | 25 | allprojects { 26 | repositories { 27 | maven { 28 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 29 | url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android')) 30 | } 31 | maven { 32 | // Android JSC is installed from npm 33 | url(new File(['node', '--print', "require.resolve('jsc-android/package.json')"].execute(null, rootDir).text.trim(), '../dist')) 34 | } 35 | 36 | google() 37 | mavenCentral() 38 | maven { url 'https://www.jitpack.io' } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /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 | 25 | # Automatically convert third-party libraries to use AndroidX 26 | android.enableJetifier=true 27 | 28 | # Version of flipper SDK to use with React Native 29 | FLIPPER_VERSION=0.182.0 30 | 31 | # Use this property to specify which architecture you want to build. 32 | # You can also override it from the CLI using 33 | # ./gradlew -PreactNativeArchitectures=x86_64 34 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 35 | 36 | # Use this property to enable support to the new architecture. 37 | # This will allow you to use TurboModules and the Fabric render in 38 | # your application. You should enable this flag either if you want 39 | # to write custom TurboModules/Fabric components OR use libraries that 40 | # are providing them. 41 | newArchEnabled=false 42 | 43 | # Use this property to enable or disable the Hermes JS engine. 44 | # If set to false, you will be using JSC instead. 45 | hermesEnabled=true 46 | 47 | # Enable GIF support in React Native images (~200 B increase) 48 | expo.gif.enabled=true 49 | # Enable webp support in React Native images (~85 KB increase) 50 | expo.webp.enabled=true 51 | # Enable animated webp support (~3.4 MB increase) 52 | # Disabled by default because iOS doesn't support animated webp 53 | expo.webp.animated=false 54 | 55 | # Enable network inspector 56 | EX_DEV_CLIENT_NETWORK_INSPECTOR=true 57 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /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 | # Stop when "xargs" is not available. 209 | if ! command -v xargs >/dev/null 2>&1 210 | then 211 | die "xargs is not available" 212 | fi 213 | 214 | # Use "xargs" to parse quoted args. 215 | # 216 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 217 | # 218 | # In Bash we could simply go: 219 | # 220 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 221 | # set -- "${ARGS[@]}" "$@" 222 | # 223 | # but POSIX shell has neither arrays nor command substitution, so instead we 224 | # post-process each arg (as a line of input to sed) to backslash-escape any 225 | # character that might be a shell metacharacter, then use eval to reverse 226 | # that process (while maintaining the separation between arguments), and wrap 227 | # the whole thing up as a single "set" statement. 228 | # 229 | # This will of course break if any of these variables contains a newline or 230 | # an unmatched quote. 231 | # 232 | 233 | eval "set -- $( 234 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 235 | xargs -n1 | 236 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 237 | tr '\n' ' ' 238 | )" '"$@"' 239 | 240 | exec "$JAVACMD" "$@" 241 | -------------------------------------------------------------------------------- /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% equ 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% equ 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 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Shopzy' 2 | 3 | apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle"); 4 | useExpoModules() 5 | 6 | apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle"); 7 | applyNativeModulesSettingsGradle(settings) 8 | 9 | include ':app' 10 | includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile()) 11 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Shopzy", 4 | "slug": "Shopzy", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/images/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "assetBundlePatterns": ["**/*"], 15 | "ios": { 16 | "supportsTablet": true, 17 | "bundleIdentifier": "com.shopzy.app" 18 | }, 19 | "android": { 20 | "adaptiveIcon": { 21 | "foregroundImage": "./assets/images/adaptive-icon.png", 22 | "backgroundColor": "#ffffff" 23 | }, 24 | "package": "com.shopzy.app" 25 | }, 26 | "web": { 27 | "favicon": "./assets/images/favicon.png" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /assets/fonts/Manrope-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/fonts/Manrope-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Manrope-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/fonts/Manrope-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/Manrope-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/fonts/Manrope-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Manrope-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/fonts/Manrope-SemiBold.ttf -------------------------------------------------------------------------------- /assets/fonts/index.ts: -------------------------------------------------------------------------------- 1 | import ManropeRegular from "./Manrope-Regular.ttf"; 2 | import ManropeMedium from "./Manrope-Medium.ttf"; 3 | import ManropeSemiBold from "./Manrope-SemiBold.ttf"; 4 | import ManropeBold from "./Manrope-Bold.ttf"; 5 | 6 | export { ManropeRegular, ManropeMedium, ManropeSemiBold, ManropeBold }; 7 | -------------------------------------------------------------------------------- /assets/images/NoNetwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/NoNetwork.png -------------------------------------------------------------------------------- /assets/images/ProductFallbackImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/ProductFallbackImage.png -------------------------------------------------------------------------------- /assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/assets/images/splash.png -------------------------------------------------------------------------------- /assets/svg/Arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/Cart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/svg/Category.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /assets/svg/DoneIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/Heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/svg/Home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/LikeIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/PlusIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/SearchIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/svg/ThreeDotsVertical.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/svg/index.ts: -------------------------------------------------------------------------------- 1 | import CartIcon from './Cart.svg'; 2 | import CategoryIcon from './Category.svg'; 3 | import HeartIcon from './Heart.svg'; 4 | import HomeIcon from './Home.svg'; 5 | import SearchIcon from './SearchIcon.svg'; 6 | import ThreeVerticalDotsIcon from './ThreeDotsVertical.svg'; 7 | import ArrowIcon from './Arrow.svg'; 8 | import LikeIcon from './LikeIcon.svg'; 9 | import PlusIcon from './PlusIcon.svg'; 10 | import DoneIcon from './DoneIcon.svg'; 11 | 12 | export { 13 | CartIcon, 14 | CategoryIcon, 15 | HeartIcon, 16 | HomeIcon, 17 | SearchIcon, 18 | ThreeVerticalDotsIcon, 19 | ArrowIcon, 20 | LikeIcon, 21 | PlusIcon, 22 | DoneIcon, 23 | }; 24 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ["babel-preset-expo"], 5 | plugins: [ 6 | [ 7 | "module-resolver", 8 | { 9 | alias: { 10 | "@app": "./src", 11 | "@assets": "./assets", 12 | }, 13 | }, 14 | ], 15 | ], 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /ios/.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 | project.xcworkspace 24 | .xcode.env.local 25 | 26 | # Bundle artifacts 27 | *.jsbundle 28 | 29 | # CocoaPods 30 | /Pods/ 31 | -------------------------------------------------------------------------------- /ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") 2 | require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods") 3 | 4 | require 'json' 5 | podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} 6 | 7 | ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0' 8 | ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR'] 9 | 10 | platform :ios, podfile_properties['ios.deploymentTarget'] || '13.0' 11 | install! 'cocoapods', 12 | :deterministic_uuids => false 13 | 14 | prepare_react_native_project! 15 | 16 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. 17 | # because `react-native-flipper` depends on (FlipperKit,...), which will be excluded. To fix this, 18 | # you can also exclude `react-native-flipper` in `react-native.config.js` 19 | # 20 | # ```js 21 | # module.exports = { 22 | # dependencies: { 23 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), 24 | # } 25 | # } 26 | # ``` 27 | flipper_config = FlipperConfiguration.disabled 28 | if ENV['NO_FLIPPER'] == '1' then 29 | # Explicitly disabled through environment variables 30 | flipper_config = FlipperConfiguration.disabled 31 | elsif podfile_properties.key?('ios.flipper') then 32 | # Configure Flipper in Podfile.properties.json 33 | if podfile_properties['ios.flipper'] == 'true' then 34 | flipper_config = FlipperConfiguration.enabled(["Debug", "Release"]) 35 | elsif podfile_properties['ios.flipper'] != 'false' then 36 | flipper_config = FlipperConfiguration.enabled(["Debug", "Release"], { 'Flipper' => podfile_properties['ios.flipper'] }) 37 | end 38 | end 39 | 40 | target 'Shopzy' do 41 | use_expo_modules! 42 | config = use_native_modules! 43 | 44 | use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks'] 45 | use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS'] 46 | 47 | # Flags change depending on the env values. 48 | flags = get_default_flags() 49 | 50 | use_react_native!( 51 | :path => config[:reactNativePath], 52 | :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes', 53 | :fabric_enabled => flags[:fabric_enabled], 54 | # An absolute path to your application root. 55 | :app_path => "#{Pod::Config.instance.installation_root}/..", 56 | # Note that if you have use_frameworks! enabled, Flipper will not work if enabled 57 | :flipper_configuration => flipper_config 58 | ) 59 | 60 | post_install do |installer| 61 | react_native_post_install( 62 | installer, 63 | config[:reactNativePath], 64 | :mac_catalyst_enabled => false 65 | ) 66 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 67 | 68 | # This is necessary for Xcode 14, because it signs resource bundles by default 69 | # when building for devices. 70 | installer.target_installation_results.pod_target_installation_results 71 | .each do |pod_name, target_installation_result| 72 | target_installation_result.resource_bundle_targets.each do |resource_bundle_target| 73 | resource_bundle_target.build_configurations.each do |config| 74 | config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO' 75 | end 76 | end 77 | end 78 | end 79 | 80 | post_integrate do |installer| 81 | begin 82 | expo_patch_react_imports!(installer) 83 | rescue => e 84 | Pod::UI.warn e 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - boost (1.76.0) 3 | - DoubleConversion (1.1.6) 4 | - EXApplication (5.3.1): 5 | - ExpoModulesCore 6 | - EXConstants (14.4.2): 7 | - ExpoModulesCore 8 | - EXFileSystem (15.4.5): 9 | - ExpoModulesCore 10 | - EXFont (11.4.0): 11 | - ExpoModulesCore 12 | - Expo (49.0.20): 13 | - ExpoModulesCore 14 | - ExpoKeepAwake (12.3.0): 15 | - ExpoModulesCore 16 | - ExpoModulesCore (1.5.12): 17 | - RCT-Folly (= 2021.07.22.00) 18 | - React-Core 19 | - React-NativeModulesApple 20 | - React-RCTAppDelegate 21 | - ReactCommon/turbomodule/core 22 | - EXSplashScreen (0.20.5): 23 | - ExpoModulesCore 24 | - RCT-Folly (= 2021.07.22.00) 25 | - React-Core 26 | - FBLazyVector (0.72.6) 27 | - FBReactNativeSpec (0.72.6): 28 | - RCT-Folly (= 2021.07.22.00) 29 | - RCTRequired (= 0.72.6) 30 | - RCTTypeSafety (= 0.72.6) 31 | - React-Core (= 0.72.6) 32 | - React-jsi (= 0.72.6) 33 | - ReactCommon/turbomodule/core (= 0.72.6) 34 | - fmt (6.2.1) 35 | - glog (0.3.5) 36 | - hermes-engine (0.72.7): 37 | - hermes-engine/Pre-built (= 0.72.7) 38 | - hermes-engine/Pre-built (0.72.7) 39 | - libevent (2.1.12) 40 | - RCT-Folly (2021.07.22.00): 41 | - boost 42 | - DoubleConversion 43 | - fmt (~> 6.2.1) 44 | - glog 45 | - RCT-Folly/Default (= 2021.07.22.00) 46 | - RCT-Folly/Default (2021.07.22.00): 47 | - boost 48 | - DoubleConversion 49 | - fmt (~> 6.2.1) 50 | - glog 51 | - RCT-Folly/Futures (2021.07.22.00): 52 | - boost 53 | - DoubleConversion 54 | - fmt (~> 6.2.1) 55 | - glog 56 | - libevent 57 | - RCTRequired (0.72.6) 58 | - RCTTypeSafety (0.72.6): 59 | - FBLazyVector (= 0.72.6) 60 | - RCTRequired (= 0.72.6) 61 | - React-Core (= 0.72.6) 62 | - React (0.72.6): 63 | - React-Core (= 0.72.6) 64 | - React-Core/DevSupport (= 0.72.6) 65 | - React-Core/RCTWebSocket (= 0.72.6) 66 | - React-RCTActionSheet (= 0.72.6) 67 | - React-RCTAnimation (= 0.72.6) 68 | - React-RCTBlob (= 0.72.6) 69 | - React-RCTImage (= 0.72.6) 70 | - React-RCTLinking (= 0.72.6) 71 | - React-RCTNetwork (= 0.72.6) 72 | - React-RCTSettings (= 0.72.6) 73 | - React-RCTText (= 0.72.6) 74 | - React-RCTVibration (= 0.72.6) 75 | - React-callinvoker (0.72.6) 76 | - React-Codegen (0.72.6): 77 | - DoubleConversion 78 | - FBReactNativeSpec 79 | - glog 80 | - hermes-engine 81 | - RCT-Folly 82 | - RCTRequired 83 | - RCTTypeSafety 84 | - React-Core 85 | - React-jsi 86 | - React-jsiexecutor 87 | - React-NativeModulesApple 88 | - React-rncore 89 | - ReactCommon/turbomodule/bridging 90 | - ReactCommon/turbomodule/core 91 | - React-Core (0.72.6): 92 | - glog 93 | - hermes-engine 94 | - RCT-Folly (= 2021.07.22.00) 95 | - React-Core/Default (= 0.72.6) 96 | - React-cxxreact 97 | - React-hermes 98 | - React-jsi 99 | - React-jsiexecutor 100 | - React-perflogger 101 | - React-runtimeexecutor 102 | - React-utils 103 | - SocketRocket (= 0.6.1) 104 | - Yoga 105 | - React-Core/CoreModulesHeaders (0.72.6): 106 | - glog 107 | - hermes-engine 108 | - RCT-Folly (= 2021.07.22.00) 109 | - React-Core/Default 110 | - React-cxxreact 111 | - React-hermes 112 | - React-jsi 113 | - React-jsiexecutor 114 | - React-perflogger 115 | - React-runtimeexecutor 116 | - React-utils 117 | - SocketRocket (= 0.6.1) 118 | - Yoga 119 | - React-Core/Default (0.72.6): 120 | - glog 121 | - hermes-engine 122 | - RCT-Folly (= 2021.07.22.00) 123 | - React-cxxreact 124 | - React-hermes 125 | - React-jsi 126 | - React-jsiexecutor 127 | - React-perflogger 128 | - React-runtimeexecutor 129 | - React-utils 130 | - SocketRocket (= 0.6.1) 131 | - Yoga 132 | - React-Core/DevSupport (0.72.6): 133 | - glog 134 | - hermes-engine 135 | - RCT-Folly (= 2021.07.22.00) 136 | - React-Core/Default (= 0.72.6) 137 | - React-Core/RCTWebSocket (= 0.72.6) 138 | - React-cxxreact 139 | - React-hermes 140 | - React-jsi 141 | - React-jsiexecutor 142 | - React-jsinspector (= 0.72.6) 143 | - React-perflogger 144 | - React-runtimeexecutor 145 | - React-utils 146 | - SocketRocket (= 0.6.1) 147 | - Yoga 148 | - React-Core/RCTActionSheetHeaders (0.72.6): 149 | - glog 150 | - hermes-engine 151 | - RCT-Folly (= 2021.07.22.00) 152 | - React-Core/Default 153 | - React-cxxreact 154 | - React-hermes 155 | - React-jsi 156 | - React-jsiexecutor 157 | - React-perflogger 158 | - React-runtimeexecutor 159 | - React-utils 160 | - SocketRocket (= 0.6.1) 161 | - Yoga 162 | - React-Core/RCTAnimationHeaders (0.72.6): 163 | - glog 164 | - hermes-engine 165 | - RCT-Folly (= 2021.07.22.00) 166 | - React-Core/Default 167 | - React-cxxreact 168 | - React-hermes 169 | - React-jsi 170 | - React-jsiexecutor 171 | - React-perflogger 172 | - React-runtimeexecutor 173 | - React-utils 174 | - SocketRocket (= 0.6.1) 175 | - Yoga 176 | - React-Core/RCTBlobHeaders (0.72.6): 177 | - glog 178 | - hermes-engine 179 | - RCT-Folly (= 2021.07.22.00) 180 | - React-Core/Default 181 | - React-cxxreact 182 | - React-hermes 183 | - React-jsi 184 | - React-jsiexecutor 185 | - React-perflogger 186 | - React-runtimeexecutor 187 | - React-utils 188 | - SocketRocket (= 0.6.1) 189 | - Yoga 190 | - React-Core/RCTImageHeaders (0.72.6): 191 | - glog 192 | - hermes-engine 193 | - RCT-Folly (= 2021.07.22.00) 194 | - React-Core/Default 195 | - React-cxxreact 196 | - React-hermes 197 | - React-jsi 198 | - React-jsiexecutor 199 | - React-perflogger 200 | - React-runtimeexecutor 201 | - React-utils 202 | - SocketRocket (= 0.6.1) 203 | - Yoga 204 | - React-Core/RCTLinkingHeaders (0.72.6): 205 | - glog 206 | - hermes-engine 207 | - RCT-Folly (= 2021.07.22.00) 208 | - React-Core/Default 209 | - React-cxxreact 210 | - React-hermes 211 | - React-jsi 212 | - React-jsiexecutor 213 | - React-perflogger 214 | - React-runtimeexecutor 215 | - React-utils 216 | - SocketRocket (= 0.6.1) 217 | - Yoga 218 | - React-Core/RCTNetworkHeaders (0.72.6): 219 | - glog 220 | - hermes-engine 221 | - RCT-Folly (= 2021.07.22.00) 222 | - React-Core/Default 223 | - React-cxxreact 224 | - React-hermes 225 | - React-jsi 226 | - React-jsiexecutor 227 | - React-perflogger 228 | - React-runtimeexecutor 229 | - React-utils 230 | - SocketRocket (= 0.6.1) 231 | - Yoga 232 | - React-Core/RCTSettingsHeaders (0.72.6): 233 | - glog 234 | - hermes-engine 235 | - RCT-Folly (= 2021.07.22.00) 236 | - React-Core/Default 237 | - React-cxxreact 238 | - React-hermes 239 | - React-jsi 240 | - React-jsiexecutor 241 | - React-perflogger 242 | - React-runtimeexecutor 243 | - React-utils 244 | - SocketRocket (= 0.6.1) 245 | - Yoga 246 | - React-Core/RCTTextHeaders (0.72.6): 247 | - glog 248 | - hermes-engine 249 | - RCT-Folly (= 2021.07.22.00) 250 | - React-Core/Default 251 | - React-cxxreact 252 | - React-hermes 253 | - React-jsi 254 | - React-jsiexecutor 255 | - React-perflogger 256 | - React-runtimeexecutor 257 | - React-utils 258 | - SocketRocket (= 0.6.1) 259 | - Yoga 260 | - React-Core/RCTVibrationHeaders (0.72.6): 261 | - glog 262 | - hermes-engine 263 | - RCT-Folly (= 2021.07.22.00) 264 | - React-Core/Default 265 | - React-cxxreact 266 | - React-hermes 267 | - React-jsi 268 | - React-jsiexecutor 269 | - React-perflogger 270 | - React-runtimeexecutor 271 | - React-utils 272 | - SocketRocket (= 0.6.1) 273 | - Yoga 274 | - React-Core/RCTWebSocket (0.72.6): 275 | - glog 276 | - hermes-engine 277 | - RCT-Folly (= 2021.07.22.00) 278 | - React-Core/Default (= 0.72.6) 279 | - React-cxxreact 280 | - React-hermes 281 | - React-jsi 282 | - React-jsiexecutor 283 | - React-perflogger 284 | - React-runtimeexecutor 285 | - React-utils 286 | - SocketRocket (= 0.6.1) 287 | - Yoga 288 | - React-CoreModules (0.72.6): 289 | - RCT-Folly (= 2021.07.22.00) 290 | - RCTTypeSafety (= 0.72.6) 291 | - React-Codegen (= 0.72.6) 292 | - React-Core/CoreModulesHeaders (= 0.72.6) 293 | - React-jsi (= 0.72.6) 294 | - React-RCTBlob 295 | - React-RCTImage (= 0.72.6) 296 | - ReactCommon/turbomodule/core (= 0.72.6) 297 | - SocketRocket (= 0.6.1) 298 | - React-cxxreact (0.72.6): 299 | - boost (= 1.76.0) 300 | - DoubleConversion 301 | - glog 302 | - hermes-engine 303 | - RCT-Folly (= 2021.07.22.00) 304 | - React-callinvoker (= 0.72.6) 305 | - React-debug (= 0.72.6) 306 | - React-jsi (= 0.72.6) 307 | - React-jsinspector (= 0.72.6) 308 | - React-logger (= 0.72.6) 309 | - React-perflogger (= 0.72.6) 310 | - React-runtimeexecutor (= 0.72.6) 311 | - React-debug (0.72.6) 312 | - React-hermes (0.72.6): 313 | - DoubleConversion 314 | - glog 315 | - hermes-engine 316 | - RCT-Folly (= 2021.07.22.00) 317 | - RCT-Folly/Futures (= 2021.07.22.00) 318 | - React-cxxreact (= 0.72.6) 319 | - React-jsi 320 | - React-jsiexecutor (= 0.72.6) 321 | - React-jsinspector (= 0.72.6) 322 | - React-perflogger (= 0.72.6) 323 | - React-jsi (0.72.6): 324 | - boost (= 1.76.0) 325 | - DoubleConversion 326 | - glog 327 | - hermes-engine 328 | - RCT-Folly (= 2021.07.22.00) 329 | - React-jsiexecutor (0.72.6): 330 | - DoubleConversion 331 | - glog 332 | - hermes-engine 333 | - RCT-Folly (= 2021.07.22.00) 334 | - React-cxxreact (= 0.72.6) 335 | - React-jsi (= 0.72.6) 336 | - React-perflogger (= 0.72.6) 337 | - React-jsinspector (0.72.6) 338 | - React-logger (0.72.6): 339 | - glog 340 | - react-native-safe-area-context (4.6.3): 341 | - RCT-Folly 342 | - RCTRequired 343 | - RCTTypeSafety 344 | - React-Core 345 | - ReactCommon/turbomodule/core 346 | - React-NativeModulesApple (0.72.6): 347 | - hermes-engine 348 | - React-callinvoker 349 | - React-Core 350 | - React-cxxreact 351 | - React-jsi 352 | - React-runtimeexecutor 353 | - ReactCommon/turbomodule/bridging 354 | - ReactCommon/turbomodule/core 355 | - React-perflogger (0.72.6) 356 | - React-RCTActionSheet (0.72.6): 357 | - React-Core/RCTActionSheetHeaders (= 0.72.6) 358 | - React-RCTAnimation (0.72.6): 359 | - RCT-Folly (= 2021.07.22.00) 360 | - RCTTypeSafety (= 0.72.6) 361 | - React-Codegen (= 0.72.6) 362 | - React-Core/RCTAnimationHeaders (= 0.72.6) 363 | - React-jsi (= 0.72.6) 364 | - ReactCommon/turbomodule/core (= 0.72.6) 365 | - React-RCTAppDelegate (0.72.6): 366 | - RCT-Folly 367 | - RCTRequired 368 | - RCTTypeSafety 369 | - React-Core 370 | - React-CoreModules 371 | - React-hermes 372 | - React-NativeModulesApple 373 | - React-RCTImage 374 | - React-RCTNetwork 375 | - React-runtimescheduler 376 | - ReactCommon/turbomodule/core 377 | - React-RCTBlob (0.72.6): 378 | - hermes-engine 379 | - RCT-Folly (= 2021.07.22.00) 380 | - React-Codegen (= 0.72.6) 381 | - React-Core/RCTBlobHeaders (= 0.72.6) 382 | - React-Core/RCTWebSocket (= 0.72.6) 383 | - React-jsi (= 0.72.6) 384 | - React-RCTNetwork (= 0.72.6) 385 | - ReactCommon/turbomodule/core (= 0.72.6) 386 | - React-RCTImage (0.72.6): 387 | - RCT-Folly (= 2021.07.22.00) 388 | - RCTTypeSafety (= 0.72.6) 389 | - React-Codegen (= 0.72.6) 390 | - React-Core/RCTImageHeaders (= 0.72.6) 391 | - React-jsi (= 0.72.6) 392 | - React-RCTNetwork (= 0.72.6) 393 | - ReactCommon/turbomodule/core (= 0.72.6) 394 | - React-RCTLinking (0.72.6): 395 | - React-Codegen (= 0.72.6) 396 | - React-Core/RCTLinkingHeaders (= 0.72.6) 397 | - React-jsi (= 0.72.6) 398 | - ReactCommon/turbomodule/core (= 0.72.6) 399 | - React-RCTNetwork (0.72.6): 400 | - RCT-Folly (= 2021.07.22.00) 401 | - RCTTypeSafety (= 0.72.6) 402 | - React-Codegen (= 0.72.6) 403 | - React-Core/RCTNetworkHeaders (= 0.72.6) 404 | - React-jsi (= 0.72.6) 405 | - ReactCommon/turbomodule/core (= 0.72.6) 406 | - React-RCTSettings (0.72.6): 407 | - RCT-Folly (= 2021.07.22.00) 408 | - RCTTypeSafety (= 0.72.6) 409 | - React-Codegen (= 0.72.6) 410 | - React-Core/RCTSettingsHeaders (= 0.72.6) 411 | - React-jsi (= 0.72.6) 412 | - ReactCommon/turbomodule/core (= 0.72.6) 413 | - React-RCTText (0.72.6): 414 | - React-Core/RCTTextHeaders (= 0.72.6) 415 | - React-RCTVibration (0.72.6): 416 | - RCT-Folly (= 2021.07.22.00) 417 | - React-Codegen (= 0.72.6) 418 | - React-Core/RCTVibrationHeaders (= 0.72.6) 419 | - React-jsi (= 0.72.6) 420 | - ReactCommon/turbomodule/core (= 0.72.6) 421 | - React-rncore (0.72.6) 422 | - React-runtimeexecutor (0.72.6): 423 | - React-jsi (= 0.72.6) 424 | - React-runtimescheduler (0.72.6): 425 | - glog 426 | - hermes-engine 427 | - RCT-Folly (= 2021.07.22.00) 428 | - React-callinvoker 429 | - React-debug 430 | - React-jsi 431 | - React-runtimeexecutor 432 | - React-utils (0.72.6): 433 | - glog 434 | - RCT-Folly (= 2021.07.22.00) 435 | - React-debug 436 | - ReactCommon/turbomodule/bridging (0.72.6): 437 | - DoubleConversion 438 | - glog 439 | - hermes-engine 440 | - RCT-Folly (= 2021.07.22.00) 441 | - React-callinvoker (= 0.72.6) 442 | - React-cxxreact (= 0.72.6) 443 | - React-jsi (= 0.72.6) 444 | - React-logger (= 0.72.6) 445 | - React-perflogger (= 0.72.6) 446 | - ReactCommon/turbomodule/core (0.72.6): 447 | - DoubleConversion 448 | - glog 449 | - hermes-engine 450 | - RCT-Folly (= 2021.07.22.00) 451 | - React-callinvoker (= 0.72.6) 452 | - React-cxxreact (= 0.72.6) 453 | - React-jsi (= 0.72.6) 454 | - React-logger (= 0.72.6) 455 | - React-perflogger (= 0.72.6) 456 | - RNGestureHandler (2.12.1): 457 | - React-Core 458 | - RNReanimated (3.3.0): 459 | - DoubleConversion 460 | - FBLazyVector 461 | - glog 462 | - hermes-engine 463 | - RCT-Folly 464 | - RCTRequired 465 | - RCTTypeSafety 466 | - React-callinvoker 467 | - React-Core 468 | - React-Core/DevSupport 469 | - React-Core/RCTWebSocket 470 | - React-CoreModules 471 | - React-cxxreact 472 | - React-hermes 473 | - React-jsi 474 | - React-jsiexecutor 475 | - React-jsinspector 476 | - React-RCTActionSheet 477 | - React-RCTAnimation 478 | - React-RCTAppDelegate 479 | - React-RCTBlob 480 | - React-RCTImage 481 | - React-RCTLinking 482 | - React-RCTNetwork 483 | - React-RCTSettings 484 | - React-RCTText 485 | - ReactCommon/turbomodule/core 486 | - Yoga 487 | - RNScreens (3.22.1): 488 | - React-Core 489 | - React-RCTImage 490 | - RNSVG (13.9.0): 491 | - React-Core 492 | - SocketRocket (0.6.1) 493 | - Yoga (1.14.0) 494 | 495 | DEPENDENCIES: 496 | - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) 497 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) 498 | - EXApplication (from `../node_modules/expo-application/ios`) 499 | - EXConstants (from `../node_modules/expo-constants/ios`) 500 | - EXFileSystem (from `../node_modules/expo-file-system/ios`) 501 | - EXFont (from `../node_modules/expo-font/ios`) 502 | - Expo (from `../node_modules/expo`) 503 | - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) 504 | - ExpoModulesCore (from `../node_modules/expo-modules-core`) 505 | - EXSplashScreen (from `../node_modules/expo-splash-screen/ios`) 506 | - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) 507 | - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) 508 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) 509 | - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) 510 | - libevent (~> 2.1.12) 511 | - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) 512 | - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) 513 | - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) 514 | - React (from `../node_modules/react-native/`) 515 | - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) 516 | - React-Codegen (from `build/generated/ios`) 517 | - React-Core (from `../node_modules/react-native/`) 518 | - React-Core/RCTWebSocket (from `../node_modules/react-native/`) 519 | - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) 520 | - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) 521 | - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) 522 | - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) 523 | - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) 524 | - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) 525 | - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) 526 | - React-logger (from `../node_modules/react-native/ReactCommon/logger`) 527 | - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) 528 | - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) 529 | - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) 530 | - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) 531 | - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) 532 | - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) 533 | - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) 534 | - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) 535 | - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) 536 | - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) 537 | - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) 538 | - React-RCTText (from `../node_modules/react-native/Libraries/Text`) 539 | - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) 540 | - React-rncore (from `../node_modules/react-native/ReactCommon`) 541 | - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) 542 | - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) 543 | - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) 544 | - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) 545 | - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) 546 | - RNReanimated (from `../node_modules/react-native-reanimated`) 547 | - RNScreens (from `../node_modules/react-native-screens`) 548 | - RNSVG (from `../node_modules/react-native-svg`) 549 | - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) 550 | 551 | SPEC REPOS: 552 | trunk: 553 | - fmt 554 | - libevent 555 | - SocketRocket 556 | 557 | EXTERNAL SOURCES: 558 | boost: 559 | :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" 560 | DoubleConversion: 561 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" 562 | EXApplication: 563 | :path: "../node_modules/expo-application/ios" 564 | EXConstants: 565 | :path: "../node_modules/expo-constants/ios" 566 | EXFileSystem: 567 | :path: "../node_modules/expo-file-system/ios" 568 | EXFont: 569 | :path: "../node_modules/expo-font/ios" 570 | Expo: 571 | :path: "../node_modules/expo" 572 | ExpoKeepAwake: 573 | :path: "../node_modules/expo-keep-awake/ios" 574 | ExpoModulesCore: 575 | :path: "../node_modules/expo-modules-core" 576 | EXSplashScreen: 577 | :path: "../node_modules/expo-splash-screen/ios" 578 | FBLazyVector: 579 | :path: "../node_modules/react-native/Libraries/FBLazyVector" 580 | FBReactNativeSpec: 581 | :path: "../node_modules/react-native/React/FBReactNativeSpec" 582 | glog: 583 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" 584 | hermes-engine: 585 | :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" 586 | :tag: hermes-2023-08-07-RNv0.72.4-813b2def12bc9df02654b3e3653ae4a68d0572e0 587 | RCT-Folly: 588 | :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" 589 | RCTRequired: 590 | :path: "../node_modules/react-native/Libraries/RCTRequired" 591 | RCTTypeSafety: 592 | :path: "../node_modules/react-native/Libraries/TypeSafety" 593 | React: 594 | :path: "../node_modules/react-native/" 595 | React-callinvoker: 596 | :path: "../node_modules/react-native/ReactCommon/callinvoker" 597 | React-Codegen: 598 | :path: build/generated/ios 599 | React-Core: 600 | :path: "../node_modules/react-native/" 601 | React-CoreModules: 602 | :path: "../node_modules/react-native/React/CoreModules" 603 | React-cxxreact: 604 | :path: "../node_modules/react-native/ReactCommon/cxxreact" 605 | React-debug: 606 | :path: "../node_modules/react-native/ReactCommon/react/debug" 607 | React-hermes: 608 | :path: "../node_modules/react-native/ReactCommon/hermes" 609 | React-jsi: 610 | :path: "../node_modules/react-native/ReactCommon/jsi" 611 | React-jsiexecutor: 612 | :path: "../node_modules/react-native/ReactCommon/jsiexecutor" 613 | React-jsinspector: 614 | :path: "../node_modules/react-native/ReactCommon/jsinspector" 615 | React-logger: 616 | :path: "../node_modules/react-native/ReactCommon/logger" 617 | react-native-safe-area-context: 618 | :path: "../node_modules/react-native-safe-area-context" 619 | React-NativeModulesApple: 620 | :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" 621 | React-perflogger: 622 | :path: "../node_modules/react-native/ReactCommon/reactperflogger" 623 | React-RCTActionSheet: 624 | :path: "../node_modules/react-native/Libraries/ActionSheetIOS" 625 | React-RCTAnimation: 626 | :path: "../node_modules/react-native/Libraries/NativeAnimation" 627 | React-RCTAppDelegate: 628 | :path: "../node_modules/react-native/Libraries/AppDelegate" 629 | React-RCTBlob: 630 | :path: "../node_modules/react-native/Libraries/Blob" 631 | React-RCTImage: 632 | :path: "../node_modules/react-native/Libraries/Image" 633 | React-RCTLinking: 634 | :path: "../node_modules/react-native/Libraries/LinkingIOS" 635 | React-RCTNetwork: 636 | :path: "../node_modules/react-native/Libraries/Network" 637 | React-RCTSettings: 638 | :path: "../node_modules/react-native/Libraries/Settings" 639 | React-RCTText: 640 | :path: "../node_modules/react-native/Libraries/Text" 641 | React-RCTVibration: 642 | :path: "../node_modules/react-native/Libraries/Vibration" 643 | React-rncore: 644 | :path: "../node_modules/react-native/ReactCommon" 645 | React-runtimeexecutor: 646 | :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" 647 | React-runtimescheduler: 648 | :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" 649 | React-utils: 650 | :path: "../node_modules/react-native/ReactCommon/react/utils" 651 | ReactCommon: 652 | :path: "../node_modules/react-native/ReactCommon" 653 | RNGestureHandler: 654 | :path: "../node_modules/react-native-gesture-handler" 655 | RNReanimated: 656 | :path: "../node_modules/react-native-reanimated" 657 | RNScreens: 658 | :path: "../node_modules/react-native-screens" 659 | RNSVG: 660 | :path: "../node_modules/react-native-svg" 661 | Yoga: 662 | :path: "../node_modules/react-native/ReactCommon/yoga" 663 | 664 | SPEC CHECKSUMS: 665 | boost: 57d2868c099736d80fcd648bf211b4431e51a558 666 | DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 667 | EXApplication: 042aa2e3f05258a16962ea1a9914bf288db9c9a1 668 | EXConstants: ce5bbea779da8031ac818c36bea41b10e14d04e1 669 | EXFileSystem: f8b838a880254de42a5a7da20ed5ce12e2697c1b 670 | EXFont: 738c44c390953ebcbab075a4848bfbef025fd9ee 671 | Expo: 25b41ba5d4a3af57234dca132f6b9e1f5b0bd4b5 672 | ExpoKeepAwake: be4cbd52d9b177cde0fd66daa1913afa3161fc1d 673 | ExpoModulesCore: c480fd4e3c7c8e81f0a6ba3a7c56869f25fe016d 674 | EXSplashScreen: c0e7f2d4a640f3b875808ed0b88575538daf6d82 675 | FBLazyVector: 748c0ef74f2bf4b36cfcccf37916806940a64c32 676 | FBReactNativeSpec: 966f29e4e697de53a3b366355e8f57375c856ad9 677 | fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 678 | glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b 679 | hermes-engine: 9180d43df05c1ed658a87cc733dc3044cf90c00a 680 | libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 681 | RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 682 | RCTRequired: 28469809442eb4eb5528462705f7d852948c8a74 683 | RCTTypeSafety: e9c6c409fca2cc584e5b086862d562540cb38d29 684 | React: 769f469909b18edfe934f0539fffb319c4c61043 685 | React-callinvoker: e48ce12c83706401251921896576710d81e54763 686 | React-Codegen: a136b8094d39fd071994eaa935366e6be2239cb1 687 | React-Core: e548a186fb01c3a78a9aeeffa212d625ca9511bf 688 | React-CoreModules: d226b22d06ea1bc4e49d3c073b2c6cbb42265405 689 | React-cxxreact: 44a3560510ead6633b6e02f9fbbdd1772fb40f92 690 | React-debug: 238501490155574ae9f3f8dd1c74330eba30133e 691 | React-hermes: 46e66dc854124d7645c20bfec0a6be9542826ecd 692 | React-jsi: fbdaf4166bae60524b591b18c851b530c8cdb90c 693 | React-jsiexecutor: 3bf18ff7cb03cd8dfdce08fbbc0d15058c1d71ae 694 | React-jsinspector: 194e32c6aab382d88713ad3dd0025c5f5c4ee072 695 | React-logger: cebf22b6cf43434e471dc561e5911b40ac01d289 696 | react-native-safe-area-context: 36cc67648134e89465663b8172336a19eeda493d 697 | React-NativeModulesApple: 02e35e9a51e10c6422f04f5e4076a7c02243fff2 698 | React-perflogger: e3596db7e753f51766bceadc061936ef1472edc3 699 | React-RCTActionSheet: 17ab132c748b4471012abbcdcf5befe860660485 700 | React-RCTAnimation: c8bbaab62be5817d2a31c36d5f2571e3f7dcf099 701 | React-RCTAppDelegate: af1c7dace233deba4b933cd1d6491fe4e3584ad1 702 | React-RCTBlob: 1bcf3a0341eb8d6950009b1ddb8aefaf46996b8c 703 | React-RCTImage: 670a3486b532292649b1aef3ffddd0b495a5cee4 704 | React-RCTLinking: bd7ab853144aed463903237e615fd91d11b4f659 705 | React-RCTNetwork: be86a621f3e4724758f23ad1fdce32474ab3d829 706 | React-RCTSettings: 4f3a29a6d23ffa639db9701bc29af43f30781058 707 | React-RCTText: adde32164a243103aaba0b1dc7b0a2599733873e 708 | React-RCTVibration: 6bd85328388ac2e82ae0ca11afe48ad5555b483a 709 | React-rncore: fda7b1ae5918fa7baa259105298a5487875a57c8 710 | React-runtimeexecutor: 57d85d942862b08f6d15441a0badff2542fd233c 711 | React-runtimescheduler: f23e337008403341177fc52ee4ca94e442c17ede 712 | React-utils: fa59c9a3375fb6f4aeb66714fd3f7f76b43a9f16 713 | ReactCommon: dd03c17275c200496f346af93a7b94c53f3093a4 714 | RNGestureHandler: c0d04458598fcb26052494ae23dda8f8f5162b13 715 | RNReanimated: 9f7068e43b9358a46a688d94a5a3adb258139457 716 | RNScreens: 50ffe2fa2342eabb2d0afbe19f7c1af286bc7fb3 717 | RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315 718 | SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 719 | Yoga: b76f1acfda8212aa16b7e26bcce3983230c82603 720 | 721 | PODFILE CHECKSUM: ad18e2207e6910b1dd97f6bd261133a90a36d376 722 | 723 | COCOAPODS: 1.12.1 724 | -------------------------------------------------------------------------------- /ios/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "hermes", 3 | "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true" 4 | } 5 | -------------------------------------------------------------------------------- /ios/Shopzy.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 11 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 12 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13 | 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; 14 | 96905EF65AED1B983A6B3ABC /* libPods-Shopzy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Shopzy.a */; }; 15 | B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; 16 | BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; 17 | F4F68E16C58142A2A98C91E0 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD92F758320148B9BF334B3D /* noop-file.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 13B07F961A680F5B00A75B9A /* Shopzy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Shopzy.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Shopzy/AppDelegate.h; sourceTree = ""; }; 23 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Shopzy/AppDelegate.mm; sourceTree = ""; }; 24 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Shopzy/Images.xcassets; sourceTree = ""; }; 25 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Shopzy/Info.plist; sourceTree = ""; }; 26 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Shopzy/main.m; sourceTree = ""; }; 27 | 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Shopzy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Shopzy.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 6C2E3173556A471DD304B334 /* Pods-Shopzy.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shopzy.debug.xcconfig"; path = "Target Support Files/Pods-Shopzy/Pods-Shopzy.debug.xcconfig"; sourceTree = ""; }; 29 | 7A4D352CD337FB3A3BF06240 /* Pods-Shopzy.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shopzy.release.xcconfig"; path = "Target Support Files/Pods-Shopzy/Pods-Shopzy.release.xcconfig"; sourceTree = ""; }; 30 | AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Shopzy/SplashScreen.storyboard; sourceTree = ""; }; 31 | BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; }; 32 | DD92F758320148B9BF334B3D /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "Shopzy/noop-file.swift"; sourceTree = ""; }; 33 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 34 | F6291A21598249469CBA2D61 /* Shopzy-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Shopzy-Bridging-Header.h"; path = "Shopzy/Shopzy-Bridging-Header.h"; sourceTree = ""; }; 35 | FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Shopzy/ExpoModulesProvider.swift"; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | 96905EF65AED1B983A6B3ABC /* libPods-Shopzy.a in Frameworks */, 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 13B07FAE1A68108700A75B9A /* Shopzy */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | BB2F792B24A3F905000567C9 /* Supporting */, 54 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 55 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */, 56 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 57 | 13B07FB61A68108700A75B9A /* Info.plist */, 58 | 13B07FB71A68108700A75B9A /* main.m */, 59 | AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */, 60 | DD92F758320148B9BF334B3D /* noop-file.swift */, 61 | F6291A21598249469CBA2D61 /* Shopzy-Bridging-Header.h */, 62 | ); 63 | name = Shopzy; 64 | sourceTree = ""; 65 | }; 66 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */, 70 | 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Shopzy.a */, 71 | ); 72 | name = Frameworks; 73 | sourceTree = ""; 74 | }; 75 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | ); 79 | name = Libraries; 80 | sourceTree = ""; 81 | }; 82 | 83CBB9F61A601CBA00E9B192 = { 83 | isa = PBXGroup; 84 | children = ( 85 | 13B07FAE1A68108700A75B9A /* Shopzy */, 86 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 87 | 83CBBA001A601CBA00E9B192 /* Products */, 88 | 2D16E6871FA4F8E400B85C8A /* Frameworks */, 89 | D65327D7A22EEC0BE12398D9 /* Pods */, 90 | D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */, 91 | ); 92 | indentWidth = 2; 93 | sourceTree = ""; 94 | tabWidth = 2; 95 | usesTabs = 0; 96 | }; 97 | 83CBBA001A601CBA00E9B192 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 13B07F961A680F5B00A75B9A /* Shopzy.app */, 101 | ); 102 | name = Products; 103 | sourceTree = ""; 104 | }; 105 | 92DBD88DE9BF7D494EA9DA96 /* Shopzy */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */, 109 | ); 110 | name = Shopzy; 111 | sourceTree = ""; 112 | }; 113 | BB2F792B24A3F905000567C9 /* Supporting */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | BB2F792C24A3F905000567C9 /* Expo.plist */, 117 | ); 118 | name = Supporting; 119 | path = Shopzy/Supporting; 120 | sourceTree = ""; 121 | }; 122 | D65327D7A22EEC0BE12398D9 /* Pods */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 6C2E3173556A471DD304B334 /* Pods-Shopzy.debug.xcconfig */, 126 | 7A4D352CD337FB3A3BF06240 /* Pods-Shopzy.release.xcconfig */, 127 | ); 128 | path = Pods; 129 | sourceTree = ""; 130 | }; 131 | D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 92DBD88DE9BF7D494EA9DA96 /* Shopzy */, 135 | ); 136 | name = ExpoModulesProviders; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 13B07F861A680F5B00A75B9A /* Shopzy */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Shopzy" */; 145 | buildPhases = ( 146 | 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, 147 | FD10A7F022414F080027D42C /* Start Packager */, 148 | 27A82601173C90480E1C06EB /* [Expo] Configure project */, 149 | 13B07F871A680F5B00A75B9A /* Sources */, 150 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 151 | 13B07F8E1A680F5B00A75B9A /* Resources */, 152 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 153 | 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */, 154 | EB31541924D2981ED8352D05 /* [CP] Embed Pods Frameworks */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = Shopzy; 161 | productName = Shopzy; 162 | productReference = 13B07F961A680F5B00A75B9A /* Shopzy.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | /* End PBXNativeTarget section */ 166 | 167 | /* Begin PBXProject section */ 168 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 169 | isa = PBXProject; 170 | attributes = { 171 | LastUpgradeCheck = 1130; 172 | TargetAttributes = { 173 | 13B07F861A680F5B00A75B9A = { 174 | LastSwiftMigration = 1250; 175 | }; 176 | }; 177 | }; 178 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Shopzy" */; 179 | compatibilityVersion = "Xcode 3.2"; 180 | developmentRegion = en; 181 | hasScannedForEncodings = 0; 182 | knownRegions = ( 183 | en, 184 | Base, 185 | ); 186 | mainGroup = 83CBB9F61A601CBA00E9B192; 187 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 188 | projectDirPath = ""; 189 | projectRoot = ""; 190 | targets = ( 191 | 13B07F861A680F5B00A75B9A /* Shopzy */, 192 | ); 193 | }; 194 | /* End PBXProject section */ 195 | 196 | /* Begin PBXResourcesBuildPhase section */ 197 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 198 | isa = PBXResourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | BB2F792D24A3F905000567C9 /* Expo.plist in Resources */, 202 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 203 | 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */, 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXResourcesBuildPhase section */ 208 | 209 | /* Begin PBXShellScriptBuildPhase section */ 210 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { 211 | isa = PBXShellScriptBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | ); 215 | inputPaths = ( 216 | ); 217 | name = "Bundle React Native code and images"; 218 | outputPaths = ( 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | shellPath = /bin/sh; 222 | shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios relative | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli')\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; 223 | }; 224 | 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = { 225 | isa = PBXShellScriptBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | ); 229 | inputFileListPaths = ( 230 | ); 231 | inputPaths = ( 232 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 233 | "${PODS_ROOT}/Manifest.lock", 234 | ); 235 | name = "[CP] Check Pods Manifest.lock"; 236 | outputFileListPaths = ( 237 | ); 238 | outputPaths = ( 239 | "$(DERIVED_FILE_DIR)/Pods-Shopzy-checkManifestLockResult.txt", 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | shellPath = /bin/sh; 243 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 244 | showEnvVarsInLog = 0; 245 | }; 246 | 27A82601173C90480E1C06EB /* [Expo] Configure project */ = { 247 | isa = PBXShellScriptBuildPhase; 248 | alwaysOutOfDate = 1; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | ); 252 | inputFileListPaths = ( 253 | ); 254 | inputPaths = ( 255 | ); 256 | name = "[Expo] Configure project"; 257 | outputFileListPaths = ( 258 | ); 259 | outputPaths = ( 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-Shopzy/expo-configure-project.sh\"\n"; 264 | }; 265 | 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { 266 | isa = PBXShellScriptBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | ); 270 | inputPaths = ( 271 | "${PODS_ROOT}/Target Support Files/Pods-Shopzy/Pods-Shopzy-resources.sh", 272 | "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", 273 | "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", 274 | ); 275 | name = "[CP] Copy Pods Resources"; 276 | outputPaths = ( 277 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", 278 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | shellPath = /bin/sh; 282 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Shopzy/Pods-Shopzy-resources.sh\"\n"; 283 | showEnvVarsInLog = 0; 284 | }; 285 | EB31541924D2981ED8352D05 /* [CP] Embed Pods Frameworks */ = { 286 | isa = PBXShellScriptBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | inputPaths = ( 291 | "${PODS_ROOT}/Target Support Files/Pods-Shopzy/Pods-Shopzy-frameworks.sh", 292 | "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", 293 | ); 294 | name = "[CP] Embed Pods Frameworks"; 295 | outputPaths = ( 296 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | shellPath = /bin/sh; 300 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Shopzy/Pods-Shopzy-frameworks.sh\"\n"; 301 | showEnvVarsInLog = 0; 302 | }; 303 | FD10A7F022414F080027D42C /* Start Packager */ = { 304 | isa = PBXShellScriptBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | inputFileListPaths = ( 309 | ); 310 | inputPaths = ( 311 | ); 312 | name = "Start Packager"; 313 | outputFileListPaths = ( 314 | ); 315 | outputPaths = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | shellPath = /bin/sh; 319 | shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\nexport RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `$NODE_BINARY --print \"require('path').dirname(require.resolve('expo/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n"; 320 | showEnvVarsInLog = 0; 321 | }; 322 | /* End PBXShellScriptBuildPhase section */ 323 | 324 | /* Begin PBXSourcesBuildPhase section */ 325 | 13B07F871A680F5B00A75B9A /* Sources */ = { 326 | isa = PBXSourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, 330 | 13B07FC11A68108700A75B9A /* main.m in Sources */, 331 | B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */, 332 | F4F68E16C58142A2A98C91E0 /* noop-file.swift in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | /* End PBXSourcesBuildPhase section */ 337 | 338 | /* Begin XCBuildConfiguration section */ 339 | 13B07F941A680F5B00A75B9A /* Debug */ = { 340 | isa = XCBuildConfiguration; 341 | baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-Shopzy.debug.xcconfig */; 342 | buildSettings = { 343 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 344 | CLANG_ENABLE_MODULES = YES; 345 | CODE_SIGN_ENTITLEMENTS = Shopzy/Shopzy.entitlements; 346 | CURRENT_PROJECT_VERSION = 1; 347 | ENABLE_BITCODE = NO; 348 | GCC_PREPROCESSOR_DEFINITIONS = ( 349 | "$(inherited)", 350 | "FB_SONARKIT_ENABLED=1", 351 | ); 352 | INFOPLIST_FILE = Shopzy/Info.plist; 353 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 355 | MARKETING_VERSION = 1.0; 356 | OTHER_LDFLAGS = ( 357 | "$(inherited)", 358 | "-ObjC", 359 | "-lc++", 360 | ); 361 | OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; 362 | PRODUCT_BUNDLE_IDENTIFIER = com.shopzy.app; 363 | PRODUCT_NAME = Shopzy; 364 | SWIFT_OBJC_BRIDGING_HEADER = "Shopzy/Shopzy-Bridging-Header.h"; 365 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 366 | SWIFT_VERSION = 5.0; 367 | TARGETED_DEVICE_FAMILY = "1,2"; 368 | VERSIONING_SYSTEM = "apple-generic"; 369 | }; 370 | name = Debug; 371 | }; 372 | 13B07F951A680F5B00A75B9A /* Release */ = { 373 | isa = XCBuildConfiguration; 374 | baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-Shopzy.release.xcconfig */; 375 | buildSettings = { 376 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 377 | CLANG_ENABLE_MODULES = YES; 378 | CODE_SIGN_ENTITLEMENTS = Shopzy/Shopzy.entitlements; 379 | CURRENT_PROJECT_VERSION = 1; 380 | INFOPLIST_FILE = Shopzy/Info.plist; 381 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 382 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 383 | MARKETING_VERSION = 1.0; 384 | OTHER_LDFLAGS = ( 385 | "$(inherited)", 386 | "-ObjC", 387 | "-lc++", 388 | ); 389 | OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; 390 | PRODUCT_BUNDLE_IDENTIFIER = com.shopzy.app; 391 | PRODUCT_NAME = Shopzy; 392 | SWIFT_OBJC_BRIDGING_HEADER = "Shopzy/Shopzy-Bridging-Header.h"; 393 | SWIFT_VERSION = 5.0; 394 | TARGETED_DEVICE_FAMILY = "1,2"; 395 | VERSIONING_SYSTEM = "apple-generic"; 396 | }; 397 | name = Release; 398 | }; 399 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | ALWAYS_SEARCH_USER_PATHS = NO; 403 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 404 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 405 | CLANG_CXX_LIBRARY = "libc++"; 406 | CLANG_ENABLE_MODULES = YES; 407 | CLANG_ENABLE_OBJC_ARC = YES; 408 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 409 | CLANG_WARN_BOOL_CONVERSION = YES; 410 | CLANG_WARN_COMMA = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 413 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 420 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 422 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 423 | CLANG_WARN_STRICT_PROTOTYPES = YES; 424 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 425 | CLANG_WARN_UNREACHABLE_CODE = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 428 | COPY_PHASE_STRIP = NO; 429 | ENABLE_STRICT_OBJC_MSGSEND = YES; 430 | ENABLE_TESTABILITY = YES; 431 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; 432 | GCC_C_LANGUAGE_STANDARD = gnu99; 433 | GCC_DYNAMIC_NO_PIC = NO; 434 | GCC_NO_COMMON_BLOCKS = YES; 435 | GCC_OPTIMIZATION_LEVEL = 0; 436 | GCC_PREPROCESSOR_DEFINITIONS = ( 437 | "DEBUG=1", 438 | "$(inherited)", 439 | _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, 440 | ); 441 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 442 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 443 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 444 | GCC_WARN_UNDECLARED_SELECTOR = YES; 445 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 446 | GCC_WARN_UNUSED_FUNCTION = YES; 447 | GCC_WARN_UNUSED_VARIABLE = YES; 448 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 449 | LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; 450 | LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; 451 | MTL_ENABLE_DEBUG_INFO = YES; 452 | ONLY_ACTIVE_ARCH = YES; 453 | OTHER_CFLAGS = "$(inherited)"; 454 | OTHER_CPLUSPLUSFLAGS = "$(inherited)"; 455 | OTHER_LDFLAGS = ( 456 | "$(inherited)", 457 | "-Wl", 458 | "-ld_classic", 459 | ); 460 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; 461 | SDKROOT = iphoneos; 462 | }; 463 | name = Debug; 464 | }; 465 | 83CBBA211A601CBA00E9B192 /* Release */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | ALWAYS_SEARCH_USER_PATHS = NO; 469 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 470 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 471 | CLANG_CXX_LIBRARY = "libc++"; 472 | CLANG_ENABLE_MODULES = YES; 473 | CLANG_ENABLE_OBJC_ARC = YES; 474 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 475 | CLANG_WARN_BOOL_CONVERSION = YES; 476 | CLANG_WARN_COMMA = YES; 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 479 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 480 | CLANG_WARN_EMPTY_BODY = YES; 481 | CLANG_WARN_ENUM_CONVERSION = YES; 482 | CLANG_WARN_INFINITE_RECURSION = YES; 483 | CLANG_WARN_INT_CONVERSION = YES; 484 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 485 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 486 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 487 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 488 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 489 | CLANG_WARN_STRICT_PROTOTYPES = YES; 490 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 491 | CLANG_WARN_UNREACHABLE_CODE = YES; 492 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 493 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 494 | COPY_PHASE_STRIP = YES; 495 | ENABLE_NS_ASSERTIONS = NO; 496 | ENABLE_STRICT_OBJC_MSGSEND = YES; 497 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; 498 | GCC_C_LANGUAGE_STANDARD = gnu99; 499 | GCC_NO_COMMON_BLOCKS = YES; 500 | GCC_PREPROCESSOR_DEFINITIONS = ( 501 | "$(inherited)", 502 | _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, 503 | ); 504 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 505 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 506 | GCC_WARN_UNDECLARED_SELECTOR = YES; 507 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 508 | GCC_WARN_UNUSED_FUNCTION = YES; 509 | GCC_WARN_UNUSED_VARIABLE = YES; 510 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 511 | LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; 512 | LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; 513 | MTL_ENABLE_DEBUG_INFO = NO; 514 | OTHER_CFLAGS = "$(inherited)"; 515 | OTHER_CPLUSPLUSFLAGS = "$(inherited)"; 516 | OTHER_LDFLAGS = ( 517 | "$(inherited)", 518 | "-Wl", 519 | "-ld_classic", 520 | ); 521 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; 522 | SDKROOT = iphoneos; 523 | VALIDATE_PRODUCT = YES; 524 | }; 525 | name = Release; 526 | }; 527 | /* End XCBuildConfiguration section */ 528 | 529 | /* Begin XCConfigurationList section */ 530 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Shopzy" */ = { 531 | isa = XCConfigurationList; 532 | buildConfigurations = ( 533 | 13B07F941A680F5B00A75B9A /* Debug */, 534 | 13B07F951A680F5B00A75B9A /* Release */, 535 | ); 536 | defaultConfigurationIsVisible = 0; 537 | defaultConfigurationName = Release; 538 | }; 539 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Shopzy" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 83CBBA201A601CBA00E9B192 /* Debug */, 543 | 83CBBA211A601CBA00E9B192 /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | /* End XCConfigurationList section */ 549 | }; 550 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 551 | } 552 | -------------------------------------------------------------------------------- /ios/Shopzy.xcodeproj/xcshareddata/xcschemes/Shopzy.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 | -------------------------------------------------------------------------------- /ios/Shopzy.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Shopzy.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Shopzy/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface AppDelegate : EXAppDelegateWrapper 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /ios/Shopzy/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | 6 | @implementation AppDelegate 7 | 8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 9 | { 10 | self.moduleName = @"main"; 11 | 12 | // You can add your custom initial props in the dictionary below. 13 | // They will be passed down to the ViewController used by React Native. 14 | self.initialProps = @{}; 15 | 16 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 17 | } 18 | 19 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 20 | { 21 | #if DEBUG 22 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"]; 23 | #else 24 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 25 | #endif 26 | } 27 | 28 | // Linking API 29 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options { 30 | return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options]; 31 | } 32 | 33 | // Universal Links 34 | - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { 35 | BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; 36 | return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result; 37 | } 38 | 39 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries 40 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 41 | { 42 | return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; 43 | } 44 | 45 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries 46 | - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 47 | { 48 | return [super application:application didFailToRegisterForRemoteNotificationsWithError:error]; 49 | } 50 | 51 | // Explicitly define remote notification delegates to ensure compatibility with some third-party libraries 52 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 53 | { 54 | return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/ios/Shopzy/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "App-Icon-1024x1024@1x.png", 5 | "idiom": "universal", 6 | "platform": "ios", 7 | "size": "1024x1024" 8 | } 9 | ], 10 | "info": { 11 | "version": 1, 12 | "author": "expo" 13 | } 14 | } -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "expo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/SplashScreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/SplashScreen.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/ios/Shopzy/Images.xcassets/SplashScreen.imageset/image.png -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/SplashScreenBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /ios/Shopzy/Images.xcassets/SplashScreenBackground.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zxcodes/Shopzy/c998959d55baf650e27d93e2fff39981f9f413d0/ios/Shopzy/Images.xcassets/SplashScreenBackground.imageset/image.png -------------------------------------------------------------------------------- /ios/Shopzy/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | Shopzy 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 21 | CFBundleShortVersionString 22 | 1.0.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleURLTypes 26 | 27 | 28 | CFBundleURLSchemes 29 | 30 | com.shopzy.app 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | NSAppTransportSecurity 39 | 40 | NSAllowsArbitraryLoads 41 | 42 | NSExceptionDomains 43 | 44 | localhost 45 | 46 | NSExceptionAllowsInsecureHTTPLoads 47 | 48 | 49 | 50 | 51 | UILaunchStoryboardName 52 | SplashScreen 53 | UIRequiredDeviceCapabilities 54 | 55 | armv7 56 | 57 | UIRequiresFullScreen 58 | 59 | UIStatusBarStyle 60 | UIStatusBarStyleDefault 61 | UISupportedInterfaceOrientations 62 | 63 | UIInterfaceOrientationPortrait 64 | UIInterfaceOrientationPortraitUpsideDown 65 | 66 | UISupportedInterfaceOrientations~ipad 67 | 68 | UIInterfaceOrientationPortrait 69 | UIInterfaceOrientationPortraitUpsideDown 70 | UIInterfaceOrientationLandscapeLeft 71 | UIInterfaceOrientationLandscapeRight 72 | 73 | UIUserInterfaceStyle 74 | Light 75 | UIViewControllerBasedStatusBarAppearance 76 | 77 | 78 | -------------------------------------------------------------------------------- /ios/Shopzy/Shopzy-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /ios/Shopzy/Shopzy.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | -------------------------------------------------------------------------------- /ios/Shopzy/SplashScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ios/Shopzy/Supporting/Expo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXUpdatesCheckOnLaunch 6 | ALWAYS 7 | EXUpdatesEnabled 8 | 9 | EXUpdatesLaunchWaitMs 10 | 0 11 | EXUpdatesSDKVersion 12 | 49.0.0 13 | 14 | -------------------------------------------------------------------------------- /ios/Shopzy/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /ios/Shopzy/noop-file.swift: -------------------------------------------------------------------------------- 1 | // 2 | // @generated 3 | // A blank Swift file must be created for native modules with Swift files to work correctly. 4 | // 5 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | const { getDefaultConfig } = require("expo/metro-config"); 3 | 4 | module.exports = (() => { 5 | const config = getDefaultConfig(__dirname); 6 | 7 | const { transformer, resolver } = config; 8 | 9 | config.transformer = { 10 | ...transformer, 11 | babelTransformerPath: require.resolve("react-native-svg-transformer"), 12 | }; 13 | config.resolver = { 14 | ...resolver, 15 | assetExts: resolver.assetExts.filter((ext) => ext !== "svg"), 16 | sourceExts: [...resolver.sourceExts, "svg"], 17 | }; 18 | 19 | return config; 20 | })(); 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Shopzy", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "start-no-cache": "expo start -c", 8 | "android": "yarn expo run:android", 9 | "ios": "yarn expo run:ios", 10 | "prebuild": "npx expo prebuild", 11 | "prebuild-clean": "npx expo prebuild --clean", 12 | "xcode": "cd ios && open shopzy.xcworkspace", 13 | "android-studio": "open -a /Applications/Android\\ Studio.app ./android/", 14 | "lint": "eslint ." 15 | }, 16 | "dependencies": { 17 | "@react-navigation/bottom-tabs": "^6.5.11", 18 | "@react-navigation/native": "^6.1.9", 19 | "@react-navigation/native-stack": "^6.9.17", 20 | "expo": "^49.0.0", 21 | "expo-font": "~11.4.0", 22 | "expo-splash-screen": "~0.20.5", 23 | "expo-status-bar": "~1.6.0", 24 | "react": "18.2.0", 25 | "react-native": "0.72.6", 26 | "react-native-gesture-handler": "~2.12.0", 27 | "react-native-reanimated": "~3.3.0", 28 | "react-native-safe-area-context": "4.6.3", 29 | "react-native-screens": "~3.22.0", 30 | "react-native-svg": "13.9.0", 31 | "react-native-toast-message": "^2.1.7", 32 | "zustand": "^4.4.6" 33 | }, 34 | "devDependencies": { 35 | "@babel/core": "^7.23.3", 36 | "@react-native-community/eslint-config": "^3.2.0", 37 | "@tsconfig/react-native": "^3.0.2", 38 | "@types/react": "~18.2.14", 39 | "@typescript-eslint/eslint-plugin": "^6.12.0", 40 | "@typescript-eslint/parser": "^6.12.0", 41 | "babel-plugin-module-resolver": "^5.0.0", 42 | "eslint": "^8.54.0", 43 | "eslint-plugin-react": "^7.33.2", 44 | "eslint-plugin-react-native": "^4.1.0", 45 | "react-native-svg-transformer": "^1.1.0", 46 | "typescript": "^5.1.3" 47 | }, 48 | "private": true 49 | } 50 | -------------------------------------------------------------------------------- /src/components/AppButton.tsx: -------------------------------------------------------------------------------- 1 | import {ACTIVE_BUTTON_OPACITY} from '@app/constants'; 2 | import {AppColors, AppFonts, FontSizes} from '@app/utils'; 3 | import { 4 | GestureResponderEvent, 5 | StyleSheet, 6 | Text, 7 | TouchableOpacity, 8 | TouchableOpacityProps, 9 | ViewStyle, 10 | } from 'react-native'; 11 | 12 | /** 13 | * AppButton is a wrapper of Button component from React Native. 14 | * It exists to make few things easier such as setting predefined background colors, font colors, font sizes, and font families. 15 | * This ensures consistency across the App. 16 | 17 | * Example usage: 18 | Some Text 19 | 20 | */ 21 | 22 | type AppFontKeys = keyof typeof AppFonts; 23 | type AppColorKeys = keyof typeof AppColors; 24 | type AppFontSizes = keyof typeof FontSizes; 25 | 26 | interface AppButtonProps 27 | extends Omit { 28 | fontFamily?: AppFontKeys; 29 | fontSize?: AppFontSizes; 30 | color?: AppColorKeys; 31 | backgroundColor?: AppColorKeys; 32 | onPress: ((event: GestureResponderEvent) => void) | undefined; 33 | style?: ViewStyle; 34 | } 35 | 36 | export default ({ 37 | color = 'PureWhite', 38 | fontFamily = 'ManropeSemiBold', 39 | fontSize = 'regular', 40 | backgroundColor = 'PrimaryBlue', 41 | children, 42 | onPress, 43 | style, 44 | ...remainingProps 45 | }: AppButtonProps) => { 46 | const size = FontSizes[fontSize as keyof typeof FontSizes]; 47 | const fontColor = AppColors[color as keyof typeof AppColors]; 48 | const background = AppColors[backgroundColor as keyof typeof AppColors]; 49 | return ( 50 | 59 | 66 | {children} 67 | 68 | 69 | ); 70 | }; 71 | 72 | const styles = StyleSheet.create({ 73 | button: { 74 | paddingVertical: 16, 75 | borderRadius: 20, 76 | paddingHorizontal: 20, 77 | }, 78 | }); 79 | -------------------------------------------------------------------------------- /src/components/AppText.tsx: -------------------------------------------------------------------------------- 1 | import {AppColors, AppFonts, FontSizes} from '@app/utils'; 2 | import {Text, TextProps, TextStyle} from 'react-native'; 3 | 4 | /** 5 | * AppText is a wrapper of native Text component from React Native. 6 | * It exists to make few things easier such as setting predefined colors, font sizes, and font families. 7 | * This ensures consistency across the App. 8 | 9 | * Example usage: 11 | Some Text 12 | 13 | */ 14 | 15 | type AppFontKeys = keyof typeof AppFonts; 16 | type AppColorKeys = keyof typeof AppColors; 17 | type AppFontSizes = keyof typeof FontSizes; 18 | 19 | interface AppTextProps extends TextProps { 20 | fontFamily?: AppFontKeys; 21 | fontSize?: AppFontSizes; 22 | color?: AppColorKeys; 23 | style?: TextStyle; 24 | } 25 | 26 | export default ({ 27 | fontFamily = 'ManropeMedium', 28 | color = 'GreyDark', 29 | fontSize = 'regular', 30 | children, 31 | style, 32 | ...remainingProps 33 | }: AppTextProps) => { 34 | const size = FontSizes[fontSize as keyof typeof FontSizes]; 35 | const fontColor = AppColors[color as keyof typeof AppColors]; 36 | 37 | return ( 38 | 46 | {children} 47 | 48 | ); 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/CartButtonWithIndicator.tsx: -------------------------------------------------------------------------------- 1 | import {TAB_ICON_SIZE as CART_ICON_SIZE} from '@app/constants'; 2 | import {AppColors, isAndroid} from '@app/utils'; 3 | import {CartIcon} from '@assets/svg'; 4 | import React from 'react'; 5 | import { 6 | GestureResponderEvent, 7 | StyleSheet, 8 | TouchableOpacity, 9 | View, 10 | } from 'react-native'; 11 | import AppText from './AppText'; 12 | 13 | type CartButtonWithIndicatorProps = { 14 | quantity: number; 15 | onPress: ((event: GestureResponderEvent) => void) | undefined; 16 | cartIconColor?: string; 17 | }; 18 | 19 | export default ({ 20 | quantity = 0, 21 | onPress, 22 | cartIconColor = AppColors.PureWhite, 23 | }: CartButtonWithIndicatorProps): JSX.Element => { 24 | return ( 25 | 26 | 31 | 32 | 38 | {quantity > 9 ? '9+' : quantity} 39 | 40 | 41 | 42 | ); 43 | }; 44 | 45 | const styles = StyleSheet.create({ 46 | button: { 47 | height: 26, 48 | width: 26, 49 | }, 50 | quantityNumber: { 51 | height: 22, 52 | width: 22, 53 | borderRadius: 100, 54 | backgroundColor: AppColors.PrimaryYellow, 55 | justifyContent: 'center', 56 | alignItems: 'center', 57 | position: 'absolute', 58 | right: -9, 59 | top: -7, 60 | }, 61 | }); 62 | -------------------------------------------------------------------------------- /src/components/CartProductQuantitySelector.tsx: -------------------------------------------------------------------------------- 1 | import {FlexContainer} from '@app/containers'; 2 | import {ProductType} from '@app/types'; 3 | import React from 'react'; 4 | import {Image, StyleSheet, View} from 'react-native'; 5 | import Spacer from './Spacer'; 6 | import AppText from './AppText'; 7 | import {AppColors} from '@app/utils'; 8 | import QuickActionButton from './QuickActionButton'; 9 | import {PlusIcon} from '@assets/svg'; 10 | import {useCartStore} from '@app/store'; 11 | import {showToast} from '@app/utils/functions'; 12 | import ProductFallbackImage from '@assets/images/ProductFallbackImage.png'; 13 | 14 | type CartProductQuantitySelectorProps = { 15 | isLastProduct?: boolean; // To hide bottom border for the last item in list. 16 | productDetails: ProductType; 17 | }; 18 | 19 | export default ({ 20 | productDetails, 21 | isLastProduct, 22 | }: CartProductQuantitySelectorProps) => { 23 | const store = useCartStore(); 24 | 25 | const cartItem = (store.cart.length && 26 | store.cart.find(item => item.product.id === productDetails.id)) || { 27 | quantity: 0, 28 | }; 29 | 30 | const handleDecreaseProductQuantity = () => { 31 | if (cartItem && cartItem.quantity > 1) { 32 | store?.updateCartItemQuantity(productDetails?.id, cartItem.quantity - 1); 33 | } else { 34 | store?.removeFromCart(productDetails?.id); 35 | } 36 | }; 37 | 38 | const handleIncreaseProductQuantity = () => { 39 | if (cartItem && cartItem.quantity < 20) { 40 | store?.updateCartItemQuantity(productDetails?.id, cartItem.quantity + 1); 41 | } else { 42 | showToast('You cannot add more than 20 items!'); 43 | } 44 | }; 45 | 46 | return ( 47 | <> 48 | 49 | 50 | 59 | 60 | 61 | 62 | {productDetails.title} 63 | 64 | 65 | {`$${ 66 | productDetails.price || 0 67 | }`} 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | {cartItem.quantity} 77 | 78 | 79 | 80 | 81 | 82 | 83 | {isLastProduct ? null : ( 84 | <> 85 | 86 | 87 | 88 | )} 89 | 90 | 91 | ); 92 | }; 93 | 94 | const styles = StyleSheet.create({ 95 | bottomBorder: { 96 | borderBottomColor: AppColors.LightWhite, 97 | borderBottomWidth: 1, 98 | }, 99 | minusIcon: { 100 | width: 7, 101 | backgroundColor: AppColors.GreyDark, 102 | height: 1.1, 103 | }, 104 | }); 105 | -------------------------------------------------------------------------------- /src/components/DropdownSelector.tsx: -------------------------------------------------------------------------------- 1 | import {AppColors, isAndroid} from '@app/utils'; 2 | import {ArrowIcon} from '@assets/svg'; 3 | import React from 'react'; 4 | import { 5 | GestureResponderEvent, 6 | StyleSheet, 7 | TouchableOpacity, 8 | View, 9 | } from 'react-native'; 10 | import AppText from './AppText'; 11 | import Spacer from './Spacer'; 12 | import {ACTIVE_BUTTON_OPACITY} from '@app/constants'; 13 | 14 | type DropdownSelectorProps = { 15 | title: string; 16 | onPress: ((event: GestureResponderEvent | string) => void) | undefined; 17 | selectedValue: string; 18 | }; 19 | 20 | export default ({onPress, selectedValue, title}: DropdownSelectorProps) => { 21 | return ( 22 | 23 | 27 | {(title && title.toUpperCase()) || ''} 28 | 29 | onPress && onPress(selectedValue)} 32 | style={{paddingVertical: 5}}> 33 | 34 | {selectedValue || ''} 35 | 36 | 43 | 44 | 45 | 46 | ); 47 | }; 48 | 49 | const styles = StyleSheet.create({ 50 | dropdownButton: { 51 | flexDirection: 'row', 52 | alignItems: 'center', 53 | }, 54 | }); 55 | -------------------------------------------------------------------------------- /src/components/HorizontalBannerList.tsx: -------------------------------------------------------------------------------- 1 | import {ACTIVE_BUTTON_OPACITY} from '@app/constants'; 2 | import {ProductType} from '@app/types'; 3 | import {AppColors} from '@app/utils'; 4 | import { 5 | ActivityIndicator, 6 | Image, 7 | ScrollView, 8 | StyleSheet, 9 | TouchableOpacity, 10 | View, 11 | ViewStyle, 12 | } from 'react-native'; 13 | 14 | type HorizontalBannerListProps = { 15 | list: ProductType[] | undefined; 16 | onPress?: (product: ProductType) => void; 17 | style?: ViewStyle; 18 | }; 19 | 20 | export default ({ 21 | list = [], 22 | onPress, 23 | style, 24 | }: HorizontalBannerListProps): JSX.Element | null => { 25 | return list.length ? ( 26 | 30 | {list.map(item => { 31 | return ( 32 | onPress && onPress(item)}> 36 | 41 | 42 | ); 43 | })} 44 | 45 | ) : ( 46 | 51 | 52 | 53 | ); 54 | }; 55 | 56 | const styles = StyleSheet.create({ 57 | list: { 58 | marginLeft: 10, 59 | height: 123, 60 | }, 61 | listItem: { 62 | height: 123, 63 | width: 269, 64 | marginHorizontal: 10, 65 | borderRadius: 16, 66 | }, 67 | loadingIndicator: { 68 | marginLeft: 0, 69 | justifyContent: 'center', 70 | alignItems: 'center', 71 | }, 72 | }); 73 | -------------------------------------------------------------------------------- /src/components/ImageCarousel.tsx: -------------------------------------------------------------------------------- 1 | import {ProductType} from '@app/types'; 2 | import {AppColors} from '@app/utils'; 3 | import React, {useRef, useState} from 'react'; 4 | import { 5 | Image, 6 | NativeScrollEvent, 7 | NativeSyntheticEvent, 8 | ScrollView, 9 | StyleSheet, 10 | View, 11 | useWindowDimensions, 12 | } from 'react-native'; 13 | 14 | type ImageCarouselProps = { 15 | images: ProductType['images']; 16 | }; 17 | 18 | const ImageCarousel: React.FC = ({images}) => { 19 | const scrollViewRef = useRef(null); 20 | const [activeIndex, setActiveIndex] = useState(0); 21 | 22 | const {width} = useWindowDimensions(); 23 | 24 | const handleScroll = (event: NativeSyntheticEvent) => { 25 | const offset = event.nativeEvent.contentOffset.x; 26 | const index = Math.round(offset / width); 27 | setActiveIndex(index); 28 | }; 29 | 30 | const renderCarouselIndicators = () => { 31 | return ( 32 | 33 | {images.map((_, index) => ( 34 | 44 | ))} 45 | 46 | ); 47 | }; 48 | 49 | return ( 50 | 51 | 58 | {images.map((image, index) => ( 59 | 60 | 61 | 62 | ))} 63 | 64 | {renderCarouselIndicators()} 65 | 66 | ); 67 | }; 68 | 69 | const styles = StyleSheet.create({ 70 | container: { 71 | height: 207, 72 | }, 73 | image: { 74 | flex: 1, 75 | width: '100%', 76 | resizeMode: 'cover', 77 | }, 78 | indicatorContainer: { 79 | flexDirection: 'row', 80 | justifyContent: 'center', 81 | alignItems: 'center', 82 | position: 'absolute', 83 | bottom: 16, 84 | left: 20, 85 | }, 86 | indicator: { 87 | width: 15, 88 | height: 4, 89 | borderRadius: 100, 90 | marginHorizontal: 5, 91 | }, 92 | }); 93 | 94 | export default ImageCarousel; 95 | -------------------------------------------------------------------------------- /src/components/ProductCard.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | ACTIVE_BUTTON_OPACITY, 3 | PRODUCT_CARD_BORDER_RADIUS, 4 | } from '@app/constants'; 5 | import {FlexContainer, PaddingContainer} from '@app/containers'; 6 | import {ProductType} from '@app/types'; 7 | import {AppColors} from '@app/utils'; 8 | import ProductFallbackImage from '@assets/images/ProductFallbackImage.png'; 9 | import {DoneIcon, LikeIcon, PlusIcon} from '@assets/svg'; 10 | import { 11 | ImageBackground, 12 | ImageSourcePropType, 13 | StyleProp, 14 | StyleSheet, 15 | TouchableOpacity, 16 | ViewStyle, 17 | } from 'react-native'; 18 | import AppText from './AppText'; 19 | import QuickActionButton from './QuickActionButton'; 20 | 21 | type ProductCardProps = { 22 | style?: ViewStyle; 23 | isFavorite: boolean; 24 | productDetails: ProductType | undefined; 25 | onPress: (product: ProductType) => void; 26 | onAddToCart: (product: ProductType) => void; 27 | isProductAddedToCart?: boolean; 28 | }; 29 | 30 | type ProductImageProps = { 31 | isValidImage: boolean; 32 | source: ImageSourcePropType; 33 | style: StyleProp; 34 | isFavorite: boolean; 35 | }; 36 | 37 | const ProductImage = ({ 38 | isValidImage, 39 | source, 40 | style, 41 | isFavorite, 42 | }: ProductImageProps) => ( 43 | 49 | 57 | 58 | ); 59 | 60 | export default ({ 61 | isFavorite, 62 | onAddToCart, 63 | onPress, 64 | style, 65 | productDetails, 66 | isProductAddedToCart, 67 | }: ProductCardProps): JSX.Element => { 68 | const isValidImage = productDetails?.thumbnail !== ''; 69 | 70 | const imageSource = isValidImage 71 | ? {uri: productDetails?.thumbnail} 72 | : ProductFallbackImage; 73 | 74 | return ( 75 | productDetails && onPress(productDetails)} 78 | style={{ 79 | ...styles.productCard, 80 | ...style, 81 | }}> 82 | 92 | 93 | 94 | 95 | {`$${ 96 | productDetails?.price || 0 97 | }`} 98 | productDetails && onAddToCart(productDetails)}> 101 | {isProductAddedToCart ? ( 102 | 103 | ) : ( 104 | 105 | )} 106 | 107 | 108 | 109 | {productDetails?.title || ''} 110 | 111 | 112 | 113 | ); 114 | }; 115 | 116 | const styles = StyleSheet.create({ 117 | productCard: { 118 | flex: 1, 119 | borderRadius: PRODUCT_CARD_BORDER_RADIUS, 120 | backgroundColor: AppColors.LightWhite, 121 | marginHorizontal: 17, 122 | marginBottom: 20, 123 | }, 124 | addToCardButton: { 125 | height: 24, 126 | width: 24, 127 | backgroundColor: AppColors.PrimaryBlue, 128 | }, 129 | productName: { 130 | width: '75%', 131 | }, 132 | productFallBackImage: { 133 | height: 68, 134 | width: 68, 135 | alignSelf: 'center', 136 | marginTop: 20, 137 | }, 138 | }); 139 | -------------------------------------------------------------------------------- /src/components/ProductGridList.tsx: -------------------------------------------------------------------------------- 1 | import {useCartStore} from '@app/store'; 2 | import {ProductType} from '@app/types'; 3 | import React from 'react'; 4 | import {FlatList, FlatListProps} from 'react-native'; 5 | import ProductCard from './ProductCard'; 6 | 7 | interface ProductGridListProps extends FlatListProps { 8 | productList: ProductType[]; 9 | onAddToCart: (product: ProductType, isProductInCart: boolean) => void; 10 | onProductPress: (product: ProductType) => void; 11 | } 12 | 13 | export default ({ 14 | productList, 15 | onAddToCart, 16 | onProductPress, 17 | ...remainingProps 18 | }: Omit) => { 19 | const store = useCartStore(); 20 | return ( 21 | product.id.toString()} 27 | numColumns={2} 28 | data={productList} 29 | renderItem={({item: product}) => { 30 | const isProductInCart = store.cart.some( 31 | item => product.id === item?.product.id 32 | ); 33 | return ( 34 | onAddToCart(product, isProductInCart)} 37 | onPress={() => onProductPress(product)} 38 | isFavorite={product.isFavorite || false} 39 | productDetails={product} 40 | /> 41 | ); 42 | }} 43 | /> 44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /src/components/QuickActionButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {StyleSheet, TouchableOpacity, ViewStyle} from 'react-native'; 3 | import {FlexContainer} from '@app/containers'; 4 | import {AppColors, isAndroid} from '@app/utils'; 5 | import {ACTIVE_BUTTON_OPACITY} from '@app/constants'; 6 | 7 | type QuickActionButtonProps = { 8 | children: React.ReactNode; 9 | disabled?: boolean; 10 | style?: ViewStyle; 11 | onPress: () => void; 12 | noBackground?: boolean; 13 | }; 14 | 15 | export default ({ 16 | children, 17 | onPress, 18 | disabled, 19 | style, 20 | noBackground, 21 | }: QuickActionButtonProps) => { 22 | return ( 23 | 27 | 34 | {children} 35 | 36 | 37 | ); 38 | }; 39 | 40 | const styles = StyleSheet.create({ 41 | container: { 42 | height: isAndroid ? 40 : 36, 43 | width: isAndroid ? 40 : 36, 44 | backgroundColor: AppColors.LightWhite, 45 | borderRadius: 100, 46 | }, 47 | }); 48 | 49 | // 50 | // 51 | // 52 | -------------------------------------------------------------------------------- /src/components/Spacer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View} from 'react-native'; 3 | import {isAndroid} from '@app/utils'; 4 | 5 | type SpacerProps = { 6 | space: number; 7 | between?: boolean; 8 | }; 9 | 10 | export default function Spacer({space, between}: SpacerProps) { 11 | return space ? ( 12 | 18 | ) : null; 19 | } 20 | 21 | // 22 | -------------------------------------------------------------------------------- /src/components/StarRatingViewer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {StyleSheet, View} from 'react-native'; 3 | import AppText from './AppText'; 4 | 5 | type StarRatingViewerProps = { 6 | rating: number | undefined; 7 | }; 8 | 9 | export default ({rating = 0}: StarRatingViewerProps): JSX.Element => { 10 | const clampedRating = Math.min(5, Math.max(0, rating)); 11 | 12 | const filledStars = Math.floor(clampedRating); 13 | const emptyStars = Math.floor(5 - filledStars); 14 | 15 | const starsArray = Array.from({length: filledStars}, (_, index) => ( 16 | 22 | ★ 23 | 24 | )); 25 | 26 | const emptyStarsArray = Array.from({length: emptyStars}, (_, index) => ( 27 | 33 | ☆ 34 | 35 | )); 36 | 37 | return ( 38 | 39 | {starsArray} 40 | {emptyStarsArray} 41 | {`${rating}`} 42 | 43 | ); 44 | }; 45 | 46 | const styles = StyleSheet.create({ 47 | container: { 48 | flexDirection: 'row', 49 | alignItems: 'center', 50 | }, 51 | }); 52 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | import AppText from './AppText'; 2 | import AppButton from './AppButton'; 3 | import QuickActionButton from './QuickActionButton'; 4 | import Spacer from './Spacer'; 5 | import CartButtonWithIndicator from './CartButtonWithIndicator'; 6 | import DropdownSelector from './DropdownSelector'; 7 | import HorizontalBannerList from './HorizontalBannerList'; 8 | import ProductCard from './ProductCard'; 9 | import StarRatingViewer from './StarRatingViewer'; 10 | import ImageCarousel from './ImageCarousel'; 11 | import CartProductQuantitySelector from './CartProductQuantitySelector'; 12 | import ProductGridList from './ProductGridList'; 13 | 14 | export { 15 | AppText, 16 | Spacer, 17 | QuickActionButton, 18 | AppButton, 19 | CartButtonWithIndicator, 20 | DropdownSelector, 21 | HorizontalBannerList, 22 | ProductCard, 23 | StarRatingViewer, 24 | ImageCarousel, 25 | CartProductQuantitySelector, 26 | ProductGridList, 27 | }; 28 | -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | const TAB_ICON_SIZE = 28; 2 | const PRODUCT_CARD_BORDER_RADIUS = 12; 3 | const ACTIVE_BUTTON_OPACITY = 0.5; 4 | 5 | export {TAB_ICON_SIZE, PRODUCT_CARD_BORDER_RADIUS, ACTIVE_BUTTON_OPACITY}; 6 | -------------------------------------------------------------------------------- /src/containers/FlexContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, {PropsWithChildren} from 'react'; 2 | import {View, ViewStyle} from 'react-native'; 3 | 4 | interface FlexContainerProps extends PropsWithChildren { 5 | position?: 'start' | 'center' | 'end' | 'rowBetween' | 'columnBetween'; 6 | direction?: 'row' | 'column'; 7 | fillHeight?: boolean; 8 | style?: ViewStyle; 9 | } 10 | 11 | const FlexContainer: React.FC = ({ 12 | children, 13 | position, 14 | direction, 15 | fillHeight = false, 16 | style, 17 | }) => { 18 | const getPositionStyles = (position: string): ViewStyle => { 19 | const baseStyles: ViewStyle = { 20 | flex: fillHeight ? 1 : undefined, 21 | flexDirection: direction === 'row' ? 'row' : 'column', 22 | ...style, 23 | }; 24 | 25 | switch (position) { 26 | case 'start': 27 | return { 28 | ...baseStyles, 29 | justifyContent: 'flex-start', 30 | alignItems: direction === 'row' ? 'center' : 'flex-start', 31 | }; 32 | case 'center': 33 | return { 34 | ...baseStyles, 35 | justifyContent: 'center', 36 | alignItems: 'center', 37 | }; 38 | case 'end': 39 | return { 40 | ...baseStyles, 41 | justifyContent: 'flex-end', 42 | alignItems: direction === 'row' ? 'center' : 'flex-end', 43 | }; 44 | case 'rowBetween': 45 | return { 46 | ...baseStyles, 47 | justifyContent: 'space-between', 48 | flexDirection: 'row', 49 | alignItems: 'center', 50 | }; 51 | case 'columnBetween': 52 | return { 53 | ...baseStyles, 54 | justifyContent: 'space-between', 55 | flexDirection: 'column', 56 | }; 57 | default: 58 | return baseStyles; 59 | } 60 | }; 61 | 62 | return ( 63 | {children} 64 | ); 65 | }; 66 | 67 | export default FlexContainer; 68 | -------------------------------------------------------------------------------- /src/containers/MainContainer.tsx: -------------------------------------------------------------------------------- 1 | import {AppColors} from '@app/utils'; 2 | import {StatusBar} from 'expo-status-bar'; 3 | import React, {PropsWithChildren} from 'react'; 4 | import {ViewStyle} from 'react-native'; 5 | import {SafeAreaView} from 'react-native-safe-area-context'; 6 | 7 | type MainContainerProps = PropsWithChildren<{ 8 | style?: ViewStyle; 9 | fillHeight?: boolean; 10 | backgroundColor?: string; 11 | children: React.ReactNode; 12 | }>; 13 | 14 | export default ({ 15 | children, 16 | style, 17 | fillHeight, 18 | backgroundColor, 19 | }: MainContainerProps): JSX.Element => { 20 | return ( 21 | 30 | 31 | {children} 32 | 33 | ); 34 | }; 35 | 36 | // 37 | // {children} 38 | // 39 | -------------------------------------------------------------------------------- /src/containers/PaddingContainer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {StyleSheet, View, ViewStyle} from 'react-native'; 3 | 4 | type PaddingContainerProps = { 5 | style?: ViewStyle; 6 | children: React.ReactNode | React.ReactNode[]; 7 | }; 8 | 9 | export default ({children, style}: PaddingContainerProps) => { 10 | return ( 11 | 16 | {children} 17 | 18 | ); 19 | }; 20 | 21 | const styles = StyleSheet.create({ 22 | container: { 23 | paddingHorizontal: 20, 24 | paddingVertical: 10, 25 | }, 26 | }); 27 | 28 | // 29 | // 30 | // 31 | // 32 | -------------------------------------------------------------------------------- /src/containers/index.ts: -------------------------------------------------------------------------------- 1 | import FlexContainer from './FlexContainer'; 2 | import MainContainer from './MainContainer'; 3 | import PaddingContainer from './PaddingContainer'; 4 | export {MainContainer, FlexContainer, PaddingContainer}; 5 | -------------------------------------------------------------------------------- /src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.jpg"; 2 | declare module "*.png"; 3 | declare module "*.ttf"; 4 | declare module "*.svg" { 5 | import React from "react"; 6 | import { SvgProps } from "react-native-svg"; 7 | const content: React.FC; 8 | export default content; 9 | } 10 | -------------------------------------------------------------------------------- /src/navigation/BottomNavBar.tsx: -------------------------------------------------------------------------------- 1 | import {AppText, Spacer} from '@app/components'; 2 | import {ACTIVE_BUTTON_OPACITY, TAB_ICON_SIZE} from '@app/constants'; 3 | import {FlexContainer} from '@app/containers'; 4 | import { 5 | CategoriesScreen, 6 | FavoritesScreen, 7 | HomeScreen, 8 | MoreScreen, 9 | } from '@app/screens'; 10 | import {AppScreensParamsList} from '@app/types'; 11 | import {AppColors, isAndroid} from '@app/utils'; 12 | import { 13 | CategoryIcon, 14 | HeartIcon as FavoritesIcon, 15 | HomeIcon, 16 | ThreeVerticalDotsIcon as MoreIcon, 17 | } from '@assets/svg'; 18 | import { 19 | BottomTabBarProps, 20 | BottomTabNavigationOptions, 21 | createBottomTabNavigator, 22 | } from '@react-navigation/bottom-tabs'; 23 | import React from 'react'; 24 | import {StyleSheet, TouchableOpacity, View} from 'react-native'; 25 | 26 | const BottomTab = createBottomTabNavigator(); 27 | 28 | type TabIconProps = { 29 | isFocused: boolean; 30 | index: number; 31 | label: string; 32 | }; 33 | 34 | const bottomNavIcons = [HomeIcon, CategoryIcon, FavoritesIcon, MoreIcon]; 35 | 36 | const RenderTabIcon = ({isFocused, index, label}: TabIconProps) => { 37 | const BottomTabIcon = bottomNavIcons[index]; 38 | return ( 39 | 40 | 46 | 47 | 48 | {label} 49 | 50 | 51 | ); 52 | }; 53 | 54 | const BottomTabBar = ({state, navigation}: BottomTabBarProps) => { 55 | return ( 56 | 57 | {state.routes.map((route, index) => { 58 | const isFocused = state.index === index; 59 | const tabBarLabel = 60 | route.name === 'HomeScreen' 61 | ? 'Home' 62 | : route.name === 'CategoriesScreen' 63 | ? 'Categories' 64 | : route.name === 'FavoritesScreen' 65 | ? 'Favorites' 66 | : 'More'; 67 | 68 | const onPress = () => { 69 | const event = navigation.emit({ 70 | type: 'tabPress', 71 | target: route.key, 72 | canPreventDefault: true, 73 | }); 74 | 75 | if (!isFocused && !event.defaultPrevented) { 76 | // The `merge: true` option makes sure that the params inside the tab screen are preserved. 77 | navigation.navigate(route.name, {merge: true}); 78 | } 79 | }; 80 | return ( 81 | 86 | 91 | 92 | ); 93 | })} 94 | 95 | ); 96 | }; 97 | 98 | const bottomTabScreenOptions: BottomTabNavigationOptions = { 99 | tabBarHideOnKeyboard: true, 100 | headerShown: false, 101 | }; 102 | 103 | const initialRouteName: keyof AppScreensParamsList = 'HomeScreen'; 104 | 105 | export default () => { 106 | return ( 107 | }> 111 | 116 | 121 | 126 | 131 | 132 | ); 133 | }; 134 | 135 | const styles = StyleSheet.create({ 136 | tabIcon: { 137 | padding: 10, 138 | }, 139 | bottomTab: { 140 | flexDirection: 'row', 141 | alignItems: 'center', 142 | justifyContent: 'space-between', 143 | paddingHorizontal: 25, 144 | backgroundColor: AppColors.PureWhite, 145 | borderTopWidth: 0, 146 | height: isAndroid ? 70 : 85, 147 | borderTopLeftRadius: 30, 148 | borderTopRightRadius: 30, 149 | }, 150 | }); 151 | -------------------------------------------------------------------------------- /src/screens/Cart.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | AppButton, 3 | AppText, 4 | CartProductQuantitySelector, 5 | QuickActionButton, 6 | Spacer, 7 | } from '@app/components'; 8 | import {ACTIVE_BUTTON_OPACITY} from '@app/constants'; 9 | import {FlexContainer, MainContainer, PaddingContainer} from '@app/containers'; 10 | import {useCartStore} from '@app/store'; 11 | import {AppScreensParamsList} from '@app/types'; 12 | import {AppColors} from '@app/utils'; 13 | import {ArrowIcon} from '@assets/svg'; 14 | import {BottomTabScreenProps} from '@react-navigation/bottom-tabs'; 15 | import {ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native'; 16 | 17 | const RenderOrderDetailsText = ({ 18 | title, 19 | value, 20 | }: { 21 | title: string; 22 | value: number; 23 | }): JSX.Element => { 24 | return ( 25 | <> 26 | 27 | {title} 28 | 29 | {`$${value || 0}`} 30 | 31 | 32 | 33 | 34 | ); 35 | }; 36 | 37 | type CartScreenProps = BottomTabScreenProps; 38 | 39 | export default ({navigation}: CartScreenProps) => { 40 | const store = useCartStore(); 41 | 42 | const isCartEmpty = store.cart.length === 0; 43 | const DELIVERY_COST = 20.45; 44 | 45 | const getTotalCartPrice = (): number => { 46 | const totalCartPrice = store.cart.reduce((total, item) => { 47 | return total + item.quantity * item.product.price; 48 | }, 0); 49 | 50 | return totalCartPrice; 51 | }; 52 | 53 | return ( 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | {`Shopping Cart (${store.cart.length || 0})`} 62 | 63 | 64 | {isCartEmpty ? ( 65 | 66 | 67 | Uh oh, Looks like you haven't shopped anything! 68 | 69 | 70 | ) : ( 71 | 72 | 73 | 74 | {store.cart.map(({product}, index) => { 75 | const isLastProduct = store.cart.length - 1 === index; 76 | return ( 77 | 82 | ); 83 | })} 84 | 85 | {!isCartEmpty ? ( 86 | 87 | alert('Handle edit!')}> 90 | Edit 91 | 92 | 93 | ) : null} 94 | 95 | 96 | 97 | )} 98 | 99 | {!isCartEmpty ? ( 100 | 101 | 102 | 106 | 107 | 111 | 112 | alert('Handle checkout!')}> 113 | Proceed To checkout 114 | 115 | 116 | ) : null} 117 | 118 | ); 119 | }; 120 | 121 | const styles = StyleSheet.create({ 122 | checkoutView: { 123 | backgroundColor: AppColors.LightWhite, 124 | borderTopLeftRadius: 30, 125 | borderTopRightRadius: 30, 126 | }, 127 | noItemsIndicator: { 128 | flex: 1, 129 | justifyContent: 'center', 130 | alignItems: 'center', 131 | }, 132 | }); 133 | -------------------------------------------------------------------------------- /src/screens/Categories.tsx: -------------------------------------------------------------------------------- 1 | import {AppText} from '@app/components'; 2 | import {FlexContainer, MainContainer} from '@app/containers'; 3 | import {AppColors} from '@app/utils'; 4 | import React from 'react'; 5 | 6 | export default (): JSX.Element => { 7 | return ( 8 | 9 | 10 | Categories 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /src/screens/Favorites.tsx: -------------------------------------------------------------------------------- 1 | import {AppText, ProductGridList} from '@app/components'; 2 | import {FlexContainer, MainContainer, PaddingContainer} from '@app/containers'; 3 | import {useCartStore} from '@app/store'; 4 | import {AppScreensParamsList, ProductType} from '@app/types'; 5 | import { 6 | showProductAddedToast, 7 | showProductRemovedToast, 8 | } from '@app/utils/functions'; 9 | import {BottomTabScreenProps} from '@react-navigation/bottom-tabs'; 10 | import React from 'react'; 11 | import {StyleSheet} from 'react-native'; 12 | 13 | type FavoritesScreenProps = BottomTabScreenProps< 14 | AppScreensParamsList, 15 | 'FavoritesScreen' 16 | >; 17 | 18 | export default ({navigation}: FavoritesScreenProps): JSX.Element => { 19 | const store = useCartStore(); 20 | 21 | const navigateToProductDetails = (product: ProductType) => { 22 | navigation.navigate('ProductDetails', {product}); 23 | }; 24 | 25 | const handleOnAddToCart = ( 26 | product: ProductType, 27 | isProductInCart: boolean 28 | ) => { 29 | if (isProductInCart) { 30 | store.removeFromCart(product.id); 31 | showProductRemovedToast(product.title); 32 | } else { 33 | showProductAddedToast(product.title); 34 | store.addToCart(product, 1); 35 | } 36 | }; 37 | 38 | const areFavoritesEmpty = store.favorites.length === 0; 39 | 40 | return ( 41 | 42 | 43 | 44 | Favorites 45 | 46 | 47 | {areFavoritesEmpty ? ( 48 | 49 | 50 | Uh oh, Looks like you haven't liked anything! 51 | 52 | 53 | ) : ( 54 | ({ 59 | ...favorite, 60 | isFavorite: true, 61 | })) 62 | : [] 63 | } 64 | onAddToCart={handleOnAddToCart} 65 | onProductPress={navigateToProductDetails} 66 | /> 67 | )} 68 | 69 | ); 70 | }; 71 | 72 | const styles = StyleSheet.create({ 73 | noItemsIndicator: { 74 | flex: 1, 75 | justifyContent: 'center', 76 | alignItems: 'center', 77 | }, 78 | }); 79 | -------------------------------------------------------------------------------- /src/screens/Home.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | AppText, 3 | CartButtonWithIndicator, 4 | DropdownSelector, 5 | HorizontalBannerList, 6 | Spacer, 7 | ProductGridList, 8 | } from '@app/components'; 9 | import {FlexContainer, MainContainer, PaddingContainer} from '@app/containers'; 10 | import {useCartStore} from '@app/store'; 11 | import {AppScreensParamsList, ProductType} from '@app/types'; 12 | import {AppColors} from '@app/utils'; 13 | import { 14 | showProductAddedToast, 15 | showProductRemovedToast, 16 | } from '@app/utils/functions'; 17 | import {SearchIcon} from '@assets/svg'; 18 | import {BottomTabScreenProps} from '@react-navigation/bottom-tabs'; 19 | import {useIsFocused} from '@react-navigation/native'; 20 | import React, {useEffect, useState} from 'react'; 21 | import {RefreshControl, StyleSheet, TextInput, View} from 'react-native'; 22 | 23 | type HomeScreenProps = BottomTabScreenProps; 24 | 25 | export default ({navigation}: HomeScreenProps): JSX.Element => { 26 | const [productList, setProductList] = useState(); 27 | 28 | const store = useCartStore(); 29 | const isFocused = useIsFocused(); 30 | 31 | const getProductsList = async () => { 32 | try { 33 | const res = await fetch('https://dummyjson.com/products'); 34 | const data = await res.json(); 35 | 36 | if (Array.isArray(data.products) && data.products.length) { 37 | const updatedProducts = data.products.map((product: ProductType) => { 38 | return { 39 | ...product, 40 | isFavorite: store.favorites.some( 41 | favorite => favorite.id === product.id 42 | ), 43 | }; 44 | }); 45 | setProductList(updatedProducts); 46 | } 47 | } catch (error) { 48 | console.error('Failed to get products list!', error); 49 | } 50 | }; 51 | 52 | const navigateToProductDetails = (product: ProductType) => { 53 | navigation.navigate('ProductDetails', {product}); 54 | }; 55 | 56 | // This could have been a reusable function, but giving a function more than 2 params isn't a good practice, so repeating it makes sense. 57 | const handleOnAddToCart = ( 58 | product: ProductType, 59 | isProductInCart: boolean 60 | ) => { 61 | if (isProductInCart) { 62 | store.removeFromCart(product.id); 63 | showProductRemovedToast(product.title); 64 | } else { 65 | showProductAddedToast(product.title); 66 | store.addToCart(product, 1); 67 | } 68 | }; 69 | 70 | const ListHeaderComponent = ( 71 | <> 72 | 73 | 74 | 78 | Hey, Rahul 79 | 80 | navigation.navigate('Cart')} 83 | /> 84 | 85 | 86 | 87 | 88 | 89 | 94 | 95 | 96 | 97 | alert(value)} 101 | /> 102 | alert(value)} 106 | /> 107 | 108 | 109 | 110 | 111 | {/* Showing only 5 products on purpose. */} 112 | 116 | 117 | 118 | {productList?.length ? ( 119 | 120 | Recommended 121 | 122 | 123 | ) : null} 124 | 125 | ); 126 | 127 | useEffect(() => { 128 | getProductsList(); 129 | }, [isFocused]); 130 | 131 | return ( 132 | 136 | 145 | } 146 | onAddToCart={handleOnAddToCart} 147 | onProductPress={navigateToProductDetails} 148 | /> 149 | 150 | ); 151 | }; 152 | 153 | const styles = StyleSheet.create({ 154 | extendedHeader: { 155 | backgroundColor: AppColors.PrimaryBlue, 156 | padding: 20, 157 | }, 158 | container: { 159 | paddingHorizontal: 0, 160 | paddingVertical: 0, 161 | }, 162 | searchInput: { 163 | borderRadius: 100, 164 | backgroundColor: AppColors.DarkBlue, 165 | paddingHorizontal: 28, 166 | flexDirection: 'row', 167 | alignItems: 'center', 168 | }, 169 | textInput: { 170 | height: 56, 171 | flex: 1, 172 | color: AppColors.PureWhite, 173 | }, 174 | }); 175 | -------------------------------------------------------------------------------- /src/screens/More.tsx: -------------------------------------------------------------------------------- 1 | import {AppText} from '@app/components'; 2 | import {FlexContainer, MainContainer} from '@app/containers'; 3 | import {AppColors} from '@app/utils'; 4 | import React from 'react'; 5 | 6 | export default (): JSX.Element => { 7 | return ( 8 | 9 | 10 | More 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /src/screens/ProductDetails.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | AppButton, 3 | AppText, 4 | CartButtonWithIndicator, 5 | ImageCarousel, 6 | QuickActionButton, 7 | Spacer, 8 | StarRatingViewer, 9 | } from '@app/components'; 10 | import {FlexContainer, MainContainer, PaddingContainer} from '@app/containers'; 11 | import {useCartStore} from '@app/store'; 12 | import {AppScreensParamsList, ProductType} from '@app/types'; 13 | import {AppColors} from '@app/utils'; 14 | import { 15 | showProductAddedToast, 16 | showProductRemovedToast, 17 | showToast, 18 | } from '@app/utils/functions'; 19 | import {ArrowIcon, HeartIcon} from '@assets/svg'; 20 | import {BottomTabScreenProps} from '@react-navigation/bottom-tabs'; 21 | import {useIsFocused} from '@react-navigation/native'; 22 | import React, {useEffect, useMemo, useState} from 'react'; 23 | import { 24 | ActivityIndicator, 25 | RefreshControl, 26 | ScrollView, 27 | StyleSheet, 28 | Vibration, 29 | View, 30 | } from 'react-native'; 31 | 32 | const PriceAndDiscountIndicator = ({ 33 | price, 34 | discount, 35 | }: { 36 | price: number; 37 | discount?: number; 38 | }): JSX.Element => { 39 | return ( 40 | 41 | {`$${ 42 | price || 0 43 | }`} 44 | 45 | 46 | {`$${discount}OFF`} 47 | 48 | 49 | ); 50 | }; 51 | 52 | type ProductDetailsScreenProps = BottomTabScreenProps< 53 | AppScreensParamsList, 54 | 'ProductDetails' 55 | >; 56 | 57 | export default ({navigation, route}: ProductDetailsScreenProps) => { 58 | const {id: productId} = route.params && route.params.product; 59 | const store = useCartStore(); 60 | 61 | const [productDetails, setProductDetails] = useState(); 62 | const isFocused = useIsFocused(); 63 | 64 | const isProductInCart = store.cart.length 65 | ? store.cart.some(product => product.product.id === productDetails?.id) 66 | : false; 67 | 68 | const getProductDetails = async (productId: number) => { 69 | if (productId) { 70 | try { 71 | const res = await fetch(`https://dummyjson.com/products/${productId}`); 72 | const productData = await res.json(); 73 | 74 | if ( 75 | Object.keys(productData).length && 76 | Object.hasOwn(productData, 'id') 77 | ) { 78 | const updatedProductDetails: ProductType = { 79 | ...productData, 80 | isFavorite: store.favorites.some( 81 | favorite => favorite.id === productData.id 82 | ), 83 | }; 84 | setProductDetails(updatedProductDetails); 85 | } 86 | } catch (error) { 87 | console.error('Failed to get product details!', error); 88 | } 89 | } 90 | }; 91 | 92 | const handleAddToCart = () => { 93 | if (productDetails) { 94 | if (isProductInCart) { 95 | store.removeFromCart(productDetails.id); 96 | showProductRemovedToast(productDetails.title); 97 | } else { 98 | showProductAddedToast(productDetails.title); 99 | store.addToCart(productDetails, 1); 100 | } 101 | } 102 | }; 103 | 104 | const handleOnBuyNow = () => { 105 | if (productDetails) { 106 | store.addToCart(productDetails, 1); 107 | navigation.navigate('Cart'); 108 | } 109 | }; 110 | 111 | const isProductLoaded = 112 | productDetails && 113 | !!productDetails?.id && 114 | !!productDetails.title && 115 | !!productDetails.price; 116 | 117 | const isProductInFavorites = useMemo(() => { 118 | if (productDetails) { 119 | return store.favorites.some(product => product.id === productDetails.id); 120 | } 121 | }, [store.favorites.length, productDetails?.isFavorite]); 122 | 123 | const handleOnFavorite = () => { 124 | if (productDetails) { 125 | if (isProductInFavorites) { 126 | store.removeFromFavorites(productDetails.id); 127 | } else { 128 | store.addToFavorites(productDetails); 129 | Vibration.vibrate(5); 130 | showToast( 131 | 'Added to favorites', 132 | `${productDetails.title} has been added to your favorites!` 133 | ); 134 | } 135 | } 136 | }; 137 | 138 | useEffect(() => { 139 | getProductDetails(productId); 140 | }, [isFocused, isProductInFavorites]); 141 | 142 | return ( 143 | 144 | 145 | 146 | 147 | 148 | 149 | navigation.navigate('Cart')} 152 | cartIconColor={AppColors.GreyDark} 153 | /> 154 | 155 | 156 | 157 | getProductDetails(productId)} 164 | tintColor={AppColors.PrimaryBlue} 165 | /> 166 | }> 167 | {isProductLoaded ? ( 168 | 169 | 170 | 171 | {productDetails?.title} 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 183 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 203 | 204 | 205 | 209 | {isProductInCart ? 'Remove From Cart' : 'Add To Cart'} 210 | 211 | 212 | 213 | Buy Now 214 | 215 | 216 | 217 | Details 218 | 219 | 220 | {productDetails.description || ''} 221 | 222 | 223 | 224 | ) : ( 225 | 226 | )} 227 | 228 | 229 | ); 230 | }; 231 | 232 | const styles = StyleSheet.create({ 233 | discountTextHolder: { 234 | paddingVertical: 4, 235 | paddingHorizontal: 15, 236 | borderRadius: 100, 237 | backgroundColor: AppColors.PrimaryBlue, 238 | }, 239 | addToCartButton: { 240 | borderWidth: 1, 241 | borderColor: AppColors.PrimaryBlue, 242 | backgroundColor: undefined, 243 | flex: 1, 244 | }, 245 | favoriteButton: { 246 | borderRadius: 20, 247 | backgroundColor: AppColors.PureWhite, 248 | height: 53, 249 | width: 53, 250 | }, 251 | favoriteButtonHolder: { 252 | position: 'absolute', 253 | zIndex: 1, 254 | right: 20, 255 | top: 20, 256 | }, 257 | }); 258 | -------------------------------------------------------------------------------- /src/screens/index.ts: -------------------------------------------------------------------------------- 1 | import Cart from './Cart'; 2 | import Categories from './Categories'; 3 | import Favorites from './Favorites'; 4 | import Home from './Home'; 5 | import More from './More'; 6 | import ProductDetails from './ProductDetails'; 7 | 8 | export { 9 | Home as HomeScreen, 10 | Categories as CategoriesScreen, 11 | Favorites as FavoritesScreen, 12 | More as MoreScreen, 13 | ProductDetails as ProductDetailsScreen, 14 | Cart as CartScreen, 15 | }; 16 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import {ProductType} from '@app/types'; 2 | import {create} from 'zustand'; 3 | 4 | type CartItem = { 5 | product: ProductType; 6 | quantity: number; 7 | }; 8 | 9 | type CartStore = { 10 | cart: CartItem[]; 11 | favorites: ProductType[]; 12 | addToCart: (product: ProductType, quantity: number) => void; 13 | removeFromCart: (productId: number) => void; 14 | updateCartItemQuantity: (productId: number, newQuantity: number) => void; 15 | clearCart: () => void; 16 | addToFavorites: (product: ProductType) => void; 17 | removeFromFavorites: (productId: number) => void; 18 | }; 19 | 20 | const useCartStore = create(set => ({ 21 | cart: [], 22 | favorites: [], 23 | addToCart: (product, quantity) => { 24 | set(state => { 25 | if (!state.cart.some(item => item.product.id === product.id)) { 26 | return { 27 | cart: [ 28 | ...state.cart, 29 | { 30 | product, 31 | quantity, 32 | }, 33 | ], 34 | }; 35 | } 36 | return state; 37 | }); 38 | }, 39 | removeFromCart: productId => { 40 | set(state => ({ 41 | cart: state.cart.filter(item => item.product.id !== productId), 42 | })); 43 | }, 44 | updateCartItemQuantity: (productId, newQuantity) => { 45 | set(state => ({ 46 | cart: state.cart.map(item => 47 | item.product.id === productId ? {...item, quantity: newQuantity} : item 48 | ), 49 | })); 50 | }, 51 | clearCart: () => { 52 | set({cart: []}); 53 | }, 54 | addToFavorites: product => { 55 | set(state => { 56 | if (!state.favorites.some(fav => fav.id === product.id)) { 57 | return { 58 | favorites: [...state.favorites, product], 59 | }; 60 | } 61 | return state; 62 | }); 63 | }, 64 | removeFromFavorites: productId => { 65 | set(state => ({ 66 | favorites: state.favorites.filter(product => product.id !== productId), 67 | })); 68 | }, 69 | })); 70 | 71 | export {useCartStore}; 72 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | type AppScreensParamsList = { 2 | HomeScreen: undefined; 3 | CategoriesScreen: undefined; 4 | FavoritesScreen: undefined; 5 | MoreScreen: undefined; 6 | ProductDetails: {product: ProductType}; 7 | Cart: undefined; 8 | BottomNavBar: undefined; 9 | }; 10 | 11 | type ProductType = { 12 | id: number; 13 | title: string; 14 | description: string; 15 | price: number; 16 | discountPercentage?: number; 17 | rating?: number; 18 | stock: number; 19 | brand: string; 20 | category: string; 21 | thumbnail: string; 22 | images: string[]; 23 | isFavorite: boolean; 24 | }; 25 | 26 | type ProductsList = ProductType[]; 27 | 28 | export type {AppScreensParamsList, ProductType, ProductsList}; 29 | -------------------------------------------------------------------------------- /src/utils/functions.ts: -------------------------------------------------------------------------------- 1 | import Toast from 'react-native-toast-message'; 2 | 3 | const showToast = (text1: string, text2?: string) => { 4 | Toast.show({ 5 | type: 'info', 6 | text1: text1, 7 | text2: text2, 8 | autoHide: true, 9 | visibilityTime: 2000, 10 | topOffset: 60, 11 | position: 'top', 12 | }); 13 | }; 14 | 15 | const showProductRemovedToast = (productName: string) => { 16 | showToast( 17 | 'Product Removed', 18 | `${productName} has been removed from your cart!` 19 | ); 20 | }; 21 | 22 | const showProductAddedToast = (productName: string) => { 23 | showToast('Product Added', `${productName} has been added to your cart!`); 24 | }; 25 | 26 | export {showToast, showProductAddedToast, showProductRemovedToast}; 27 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import {Platform} from 'react-native'; 2 | 3 | const isAndroid: boolean = Platform.OS === 'android'; 4 | 5 | enum AppColors { 6 | PrimaryBlue = '#2A4BA0', 7 | DarkBlue = '#153075', 8 | PrimaryYellow = '#F9B023', 9 | PureWhite = '#FFF', 10 | Grey = '#B2BBCE', 11 | PureBlack = '#000000', 12 | LightOrange = '#FF8181', 13 | GreyLightest = '#8891A5', 14 | GreyDarkLight = '#3E4554', 15 | GreyDark = '#1E222B', 16 | LightWhite = '#F8F9FB', 17 | LightGrey = '#616A7D', 18 | } 19 | 20 | enum AppFonts { 21 | 'ManropeRegular' = 'Manrope-Regular', 22 | 'ManropeMedium' = 'Manrope-Medium', 23 | 'ManropeSemiBold' = 'Manrope-SemiBold', 24 | 'ManropeBold' = 'Manrope-Bold', 25 | } 26 | 27 | enum FontSizes { 28 | 'small' = 12, 29 | 'regular' = 14, 30 | 'medium' = 16, 31 | 'large' = 18, 32 | 'extraLarge' = 24, 33 | 'infiniteLarge' = 50, 34 | } 35 | 36 | export {AppColors, AppFonts, FontSizes, isAndroid}; 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | "@app/*": ["src/*"], 8 | "@assets/*": ["assets/*"] 9 | }, 10 | "jsx": "react-native" 11 | }, 12 | "exclude": ["node_modules"] 13 | } 14 | --------------------------------------------------------------------------------