├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── babel.config.js ├── circle.yml ├── index.test.js ├── index.tsx ├── ios ├── RNHomeIndicator.h ├── RNHomeIndicator.m └── RNHomeIndicator.xcodeproj │ └── project.pbxproj ├── package-lock.json ├── package.json ├── react-native-home-indicator.podspec └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | extends: ["@react-native-community", "plugin:@typescript-eslint/recommended", "prettier"], 4 | plugins: ["import", "@typescript-eslint"], 5 | settings: { 6 | "import/resolver": { 7 | typescript: {}, // this loads /tsconfig.json to eslint 8 | }, 9 | }, 10 | rules: { 11 | "no-param-reassign": ["error", { props: true }], 12 | "no-debugger": "error", 13 | "no-redeclare": "error", 14 | 15 | "no-unused-vars": "error", 16 | "no-nested-ternary": "error", 17 | "no-extra-boolean-cast": 0, 18 | 19 | "import/no-unresolved": "error", 20 | "import/default": "error", 21 | "import/no-self-import": "error", 22 | "import/no-unused-modules": "error", 23 | "import/no-duplicates": "error", 24 | "import/first": "warn", 25 | 26 | "react-hooks/exhaustive-deps": "warn", 27 | "react-native/no-inline-styles": "off", 28 | "react/no-did-mount-set-state": "warn", 29 | "react/jsx-curly-brace-presence": "error", 30 | "prettier/prettier": "error", 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | coverage 12 | 13 | 14 | # Xcode 15 | # 16 | build/ 17 | *.pbxuser 18 | !default.pbxuser 19 | *.mode1v3 20 | !default.mode1v3 21 | *.mode2v3 22 | !default.mode2v3 23 | *.perspectivev3 24 | !default.perspectivev3 25 | xcuserdata 26 | *.xccheckout 27 | *.moved-aside 28 | DerivedData 29 | *.hmap 30 | *.ipa 31 | *.xcuserstate 32 | project.xcworkspace 33 | 34 | 35 | # BUCK 36 | buck-out/ 37 | \.buckd/ 38 | *.keystore -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.test.js 4 | .eslintrc 5 | .eslintignore 6 | .babelrc 7 | coverage 8 | tsconfig.json 9 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "printWidth": 100, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 flowkey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm version](https://badge.fury.io/js/react-native-home-indicator.svg)](https://badge.fury.io/js/react-native-home-indicator) 2 | [![CircleCI](https://circleci.com/gh/flowkey/react-native-home-indicator.svg?style=svg)](https://circleci.com/gh/flowkey/react-native-home-indicator) 3 | [![codecov](https://codecov.io/gh/flowkey/react-native-home-indicator/branch/master/graph/badge.svg)](https://codecov.io/gh/flowkey/react-native-home-indicator) 4 | 5 | A declarative approach for hiding the [Home Indicator](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design) on iOS/iPadOS devices. 6 | ## Getting Started 7 | 8 | #### 1. Add dependency 9 | `npm install react-native-home-indicator --save` 10 | 11 | #### 2. Link library 12 | If you're using RN >= 0.60.0 just run `pod install` as usual 13 | 14 | #### 3. Changes in Appdelegate.m 15 | 16 | ```objective-c 17 | // add to your imports 18 | #import 19 | ``` 20 | 21 | ```objective-c 22 | // find this line 23 | UIViewController *rootViewController = [UIViewController new]; 24 | ``` 25 | 26 | ```objective-c 27 | // and replace with 28 | UIViewController *rootViewController = [HomeIndicatorViewController new]; 29 | ``` 30 | 31 | 32 | ## Simple Usage 33 | 34 | Render `` to signal your preference for hiding the Home Indicator. 35 | "The system takes your preference into account, but returning true is no guarantee that the indicator will be hidden." 36 | see [developer.apple.com/documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden) 37 | 38 | ```jsx 39 | ... 40 | import PrefersHomeIndicatorAutoHidden from 'react-native-home-indicator'; 41 | 42 | const SomeReactNativeComponent = () => { 43 | return ( 44 | 45 | 46 | ... 47 | 48 | ); 49 | } 50 | ``` 51 | 52 | ## Extended Usage 53 | 54 | For more complex usage you can use the `HomeIndicator` component which allows passing your preferred 55 | indicator setting as prop. Its even possible to override previous rendered indicator preferences as 56 | you can see in the following example. 57 | 58 | ```jsx 59 | ... 60 | import { HomeIndicator } from 'react-native-home-indicator'; 61 | 62 | const SomeReactNativeComponent = () => { 63 | return ( 64 | 65 | 66 | 67 | 68 | 69 | 70 | ); 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["module:metro-react-native-babel-preset"], 3 | }; 4 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/project 5 | docker: 6 | - image: circleci/node:16 7 | steps: 8 | - checkout 9 | - restore_cache: 10 | key: node_modules-{{ checksum "package-lock.json" }}-{{ checksum "package.json" }} 11 | 12 | - run: npm i 13 | 14 | - save_cache: 15 | paths: 16 | - node_modules 17 | key: node_modules-{{ checksum "package-lock.json" }}-{{ checksum "package.json" }} 18 | 19 | - run: npm run tsc 20 | - run: npm run eslint 21 | - run: 22 | name: "test and upload coverage" 23 | command: npm run test && npm run codecov 24 | environment: 25 | - CODECOV_TOKEN: "155bb51c-360b-4193-a77f-d4bb1f37ca96" 26 | -------------------------------------------------------------------------------- /index.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PrefersHomeIndicatorAutoHidden, { 3 | HomeIndicator, 4 | clearPropsHistory, 5 | getPropsHistory, 6 | popAndGetPreviousProps, 7 | } from "./"; 8 | import renderer, { act } from "react-test-renderer"; 9 | import { NativeModules, View } from "react-native"; 10 | 11 | jest.mock("react-native", () => { 12 | const RN = jest.requireActual("react-native"); 13 | RN.NativeModules.RNHomeIndicator = { 14 | autoHidden: jest.fn(), 15 | alwaysVisible: jest.fn(), 16 | }; 17 | return RN; 18 | }); 19 | 20 | const { RNHomeIndicator } = NativeModules; 21 | 22 | describe("react-native-home-indicator", () => { 23 | beforeEach(() => { 24 | clearPropsHistory(); 25 | RNHomeIndicator.autoHidden.mockReset(); 26 | RNHomeIndicator.alwaysVisible.mockReset(); 27 | }); 28 | 29 | test("hide native indicator when mounting PrefersHomeIndicatorAutoHidden", () => { 30 | act(() => { 31 | renderer.create(); 32 | }); 33 | expect(RNHomeIndicator.autoHidden).toHaveBeenCalled(); 34 | }); 35 | 36 | test("hide native indicator when mounting HomeIndicator with autoHidden=true", () => { 37 | act(() => { 38 | renderer.create(); 39 | }); 40 | expect(RNHomeIndicator.autoHidden).toHaveBeenCalled(); 41 | }); 42 | 43 | test("hide native indicator when mounting HomeIndicator with autoHidden=false", () => { 44 | act(() => { 45 | renderer.create(); 46 | }); 47 | expect(RNHomeIndicator.autoHidden).not.toHaveBeenCalled(); 48 | }); 49 | 50 | test("show indicator when unmounting PrefersHomeIndicatorAutoHidden", () => { 51 | let component; 52 | act(() => { 53 | component = renderer.create(); 54 | }); 55 | expect(RNHomeIndicator.autoHidden).toHaveBeenCalled(); 56 | 57 | act(() => { 58 | component.unmount(); 59 | }); 60 | 61 | expect(RNHomeIndicator.alwaysVisible).toHaveBeenCalled(); 62 | }); 63 | 64 | test("dont hide native indicator when another instance is currently rendered", () => { 65 | renderer.create(); 66 | const secondTree = renderer.create(); 67 | 68 | secondTree.unmount(); 69 | 70 | expect(RNHomeIndicator.alwaysVisible).not.toHaveBeenCalled(); 71 | }); 72 | 73 | test("fallback when no prop is provided", () => { 74 | act(() => { 75 | renderer.create(); 76 | }); 77 | expect(RNHomeIndicator.autoHidden).not.toHaveBeenCalled(); 78 | expect(RNHomeIndicator.alwaysVisible).toHaveBeenCalled(); 79 | }); 80 | 81 | test("propsHistory", async () => { 82 | act(() => { 83 | renderer.create( 84 | 85 | 86 | 87 | 88 | 89 | 90 | ); 91 | }); 92 | 93 | expect(getPropsHistory()).toEqual([ 94 | { autoHidden: false }, 95 | { autoHidden: true }, 96 | { autoHidden: true }, 97 | { autoHidden: false }, 98 | ]); 99 | }); 100 | 101 | test("popAndGetPreviousProps", () => { 102 | act(() => { 103 | renderer.create( 104 | 105 | 106 | 107 | 108 | 109 | 110 | ); 111 | }); 112 | 113 | expect(popAndGetPreviousProps()).toEqual({ autoHidden: true }); 114 | }); 115 | 116 | test("ensure component renders null", () => { 117 | const component = renderer.create(); 118 | expect(component.toJSON()).toEqual(null); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { NativeModules, Platform } from "react-native"; 3 | 4 | const { RNHomeIndicator } = NativeModules; 5 | const isIos = Platform.OS === "ios"; 6 | 7 | type Props = { autoHidden: boolean }; 8 | 9 | export const HomeIndicator = (props: Props) => { 10 | useEffect(() => { 11 | if (!isIos) return; 12 | 13 | propsHistory.push(props); 14 | updateNativeHomeIndicator({ autoHidden: props.autoHidden }); 15 | 16 | return () => { 17 | if (!isIos) return; 18 | 19 | const previousProps = popAndGetPreviousProps(); 20 | updateNativeHomeIndicator({ autoHidden: previousProps.autoHidden }); 21 | }; 22 | }, []); 23 | 24 | return null; 25 | }; 26 | 27 | let propsHistory: Props[] = []; 28 | 29 | export function clearPropsHistory() { 30 | propsHistory = []; 31 | } 32 | 33 | export function getPropsHistory() { 34 | return [...propsHistory]; 35 | } 36 | 37 | export function popAndGetPreviousProps() { 38 | propsHistory.pop(); 39 | return propsHistory[propsHistory.length - 1] || { autoHidden: false }; 40 | } 41 | 42 | function updateNativeHomeIndicator({ autoHidden = false }: { autoHidden: boolean }) { 43 | if (autoHidden) { 44 | RNHomeIndicator.autoHidden(); 45 | } else { 46 | RNHomeIndicator.alwaysVisible(); 47 | } 48 | } 49 | 50 | // keep this for backwards compatibility 51 | const PrefersHomeIndicatorAutoHidden = () => ; 52 | export default PrefersHomeIndicatorAutoHidden; 53 | -------------------------------------------------------------------------------- /ios/RNHomeIndicator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import 4 | 5 | 6 | @interface HomeIndicatorViewController : UIViewController 7 | @property BOOL prefersAutoHidden; 8 | @end 9 | 10 | @interface RNHomeIndicator : NSObject 11 | @end 12 | 13 | 14 | -------------------------------------------------------------------------------- /ios/RNHomeIndicator.m: -------------------------------------------------------------------------------- 1 | 2 | #import "RNHomeIndicator.h" 3 | 4 | @implementation HomeIndicatorViewController 5 | 6 | - (BOOL)prefersHomeIndicatorAutoHidden { 7 | return self.prefersAutoHidden; 8 | } 9 | 10 | @end 11 | 12 | 13 | @implementation RNHomeIndicator 14 | 15 | - (id) init { 16 | [self setPrefersAutoHidden:NO]; 17 | return [super init]; 18 | } 19 | 20 | - (void) setPrefersAutoHidden: (BOOL) newValue { 21 | HomeIndicatorViewController *rootViewController = [self getHomeIndicatorViewController]; 22 | 23 | rootViewController.prefersAutoHidden = newValue; 24 | if (@available(iOS 11.0, *)) { 25 | [rootViewController setNeedsUpdateOfHomeIndicatorAutoHidden]; 26 | } 27 | } 28 | 29 | - (HomeIndicatorViewController*) getHomeIndicatorViewController { 30 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 31 | NSAssert( 32 | [rootViewController isKindOfClass:[HomeIndicatorViewController class]], 33 | @"rootViewController is not of type HomeIndicatorViewController as expected." 34 | ); 35 | return (HomeIndicatorViewController*) rootViewController; 36 | } 37 | 38 | - (dispatch_queue_t)methodQueue { 39 | return dispatch_get_main_queue(); 40 | } 41 | 42 | + (BOOL)requiresMainQueueSetup { 43 | return YES; 44 | } 45 | 46 | RCT_EXPORT_MODULE() 47 | 48 | RCT_EXPORT_METHOD(alwaysVisible) { 49 | [self setPrefersAutoHidden:NO]; 50 | } 51 | 52 | RCT_EXPORT_METHOD(autoHidden) { 53 | [self setPrefersAutoHidden:YES]; 54 | } 55 | 56 | @end 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ios/RNHomeIndicator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B3E7B58A1CC2AC0600A0062D /* RNHomeIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNHomeIndicator.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = "include/$(PRODUCT_NAME)"; 18 | dstSubfolderSpec = 16; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 0; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 134814201AA4EA6300B7C361 /* libRNHomeIndicator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNHomeIndicator.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B3E7B5881CC2AC0600A0062D /* RNHomeIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNHomeIndicator.h; sourceTree = ""; }; 28 | B3E7B5891CC2AC0600A0062D /* RNHomeIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNHomeIndicator.m; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 134814211AA4EA7D00B7C361 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 134814201AA4EA6300B7C361 /* libRNHomeIndicator.a */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 58B511D21A9E6C8500147676 = { 51 | isa = PBXGroup; 52 | children = ( 53 | B3E7B5881CC2AC0600A0062D /* RNHomeIndicator.h */, 54 | B3E7B5891CC2AC0600A0062D /* RNHomeIndicator.m */, 55 | 134814211AA4EA7D00B7C361 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | /* End PBXGroup section */ 60 | 61 | /* Begin PBXNativeTarget section */ 62 | 58B511DA1A9E6C8500147676 /* RNHomeIndicator */ = { 63 | isa = PBXNativeTarget; 64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNHomeIndicator" */; 65 | buildPhases = ( 66 | 58B511D71A9E6C8500147676 /* Sources */, 67 | 58B511D81A9E6C8500147676 /* Frameworks */, 68 | 58B511D91A9E6C8500147676 /* CopyFiles */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = RNHomeIndicator; 75 | productName = RCTDataManager; 76 | productReference = 134814201AA4EA6300B7C361 /* libRNHomeIndicator.a */; 77 | productType = "com.apple.product-type.library.static"; 78 | }; 79 | /* End PBXNativeTarget section */ 80 | 81 | /* Begin PBXProject section */ 82 | 58B511D31A9E6C8500147676 /* Project object */ = { 83 | isa = PBXProject; 84 | attributes = { 85 | LastUpgradeCheck = 0830; 86 | ORGANIZATIONNAME = Facebook; 87 | TargetAttributes = { 88 | 58B511DA1A9E6C8500147676 = { 89 | CreatedOnToolsVersion = 6.1.1; 90 | }; 91 | }; 92 | }; 93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNHomeIndicator" */; 94 | compatibilityVersion = "Xcode 3.2"; 95 | developmentRegion = English; 96 | hasScannedForEncodings = 0; 97 | knownRegions = ( 98 | en, 99 | ); 100 | mainGroup = 58B511D21A9E6C8500147676; 101 | productRefGroup = 58B511D21A9E6C8500147676; 102 | projectDirPath = ""; 103 | projectRoot = ""; 104 | targets = ( 105 | 58B511DA1A9E6C8500147676 /* RNHomeIndicator */, 106 | ); 107 | }; 108 | /* End PBXProject section */ 109 | 110 | /* Begin PBXSourcesBuildPhase section */ 111 | 58B511D71A9E6C8500147676 /* Sources */ = { 112 | isa = PBXSourcesBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | B3E7B58A1CC2AC0600A0062D /* RNHomeIndicator.m in Sources */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXSourcesBuildPhase section */ 120 | 121 | /* Begin XCBuildConfiguration section */ 122 | 58B511ED1A9E6C8500147676 /* Debug */ = { 123 | isa = XCBuildConfiguration; 124 | buildSettings = { 125 | ALWAYS_SEARCH_USER_PATHS = NO; 126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 127 | CLANG_CXX_LIBRARY = "libc++"; 128 | CLANG_ENABLE_MODULES = YES; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INFINITE_RECURSION = YES; 136 | CLANG_WARN_INT_CONVERSION = YES; 137 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 138 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 139 | CLANG_WARN_UNREACHABLE_CODE = YES; 140 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 141 | COPY_PHASE_STRIP = NO; 142 | ENABLE_STRICT_OBJC_MSGSEND = YES; 143 | ENABLE_TESTABILITY = YES; 144 | GCC_C_LANGUAGE_STANDARD = gnu99; 145 | GCC_DYNAMIC_NO_PIC = NO; 146 | GCC_NO_COMMON_BLOCKS = YES; 147 | GCC_OPTIMIZATION_LEVEL = 0; 148 | GCC_PREPROCESSOR_DEFINITIONS = ( 149 | "DEBUG=1", 150 | "$(inherited)", 151 | ); 152 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 153 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 154 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 155 | GCC_WARN_UNDECLARED_SELECTOR = YES; 156 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 157 | GCC_WARN_UNUSED_FUNCTION = YES; 158 | GCC_WARN_UNUSED_VARIABLE = YES; 159 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 160 | MTL_ENABLE_DEBUG_INFO = YES; 161 | ONLY_ACTIVE_ARCH = YES; 162 | SDKROOT = iphoneos; 163 | }; 164 | name = Debug; 165 | }; 166 | 58B511EE1A9E6C8500147676 /* Release */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 171 | CLANG_CXX_LIBRARY = "libc++"; 172 | CLANG_ENABLE_MODULES = YES; 173 | CLANG_ENABLE_OBJC_ARC = YES; 174 | CLANG_WARN_BOOL_CONVERSION = YES; 175 | CLANG_WARN_CONSTANT_CONVERSION = YES; 176 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 177 | CLANG_WARN_EMPTY_BODY = YES; 178 | CLANG_WARN_ENUM_CONVERSION = YES; 179 | CLANG_WARN_INFINITE_RECURSION = YES; 180 | CLANG_WARN_INT_CONVERSION = YES; 181 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 182 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 183 | CLANG_WARN_UNREACHABLE_CODE = YES; 184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 185 | COPY_PHASE_STRIP = YES; 186 | ENABLE_NS_ASSERTIONS = NO; 187 | ENABLE_STRICT_OBJC_MSGSEND = YES; 188 | GCC_C_LANGUAGE_STANDARD = gnu99; 189 | GCC_NO_COMMON_BLOCKS = YES; 190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 191 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 192 | GCC_WARN_UNDECLARED_SELECTOR = YES; 193 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 194 | GCC_WARN_UNUSED_FUNCTION = YES; 195 | GCC_WARN_UNUSED_VARIABLE = YES; 196 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 197 | MTL_ENABLE_DEBUG_INFO = NO; 198 | SDKROOT = iphoneos; 199 | VALIDATE_PRODUCT = YES; 200 | }; 201 | name = Release; 202 | }; 203 | 58B511F01A9E6C8500147676 /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | HEADER_SEARCH_PATHS = ( 207 | "$(inherited)", 208 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 209 | "$(SRCROOT)/../../../React/**", 210 | "$(SRCROOT)/../../react-native/React/**", 211 | ); 212 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 213 | OTHER_LDFLAGS = "-ObjC"; 214 | PRODUCT_NAME = RNHomeIndicator; 215 | SKIP_INSTALL = YES; 216 | }; 217 | name = Debug; 218 | }; 219 | 58B511F11A9E6C8500147676 /* Release */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | HEADER_SEARCH_PATHS = ( 223 | "$(inherited)", 224 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 225 | "$(SRCROOT)/../../../React/**", 226 | "$(SRCROOT)/../../react-native/React/**", 227 | ); 228 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 229 | OTHER_LDFLAGS = "-ObjC"; 230 | PRODUCT_NAME = RNHomeIndicator; 231 | SKIP_INSTALL = YES; 232 | }; 233 | name = Release; 234 | }; 235 | /* End XCBuildConfiguration section */ 236 | 237 | /* Begin XCConfigurationList section */ 238 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNHomeIndicator" */ = { 239 | isa = XCConfigurationList; 240 | buildConfigurations = ( 241 | 58B511ED1A9E6C8500147676 /* Debug */, 242 | 58B511EE1A9E6C8500147676 /* Release */, 243 | ); 244 | defaultConfigurationIsVisible = 0; 245 | defaultConfigurationName = Release; 246 | }; 247 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNHomeIndicator" */ = { 248 | isa = XCConfigurationList; 249 | buildConfigurations = ( 250 | 58B511F01A9E6C8500147676 /* Debug */, 251 | 58B511F11A9E6C8500147676 /* Release */, 252 | ); 253 | defaultConfigurationIsVisible = 0; 254 | defaultConfigurationName = Release; 255 | }; 256 | /* End XCConfigurationList section */ 257 | }; 258 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 259 | } 260 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-home-indicator", 3 | "version": "0.2.10", 4 | "description": "A declarative approach for hiding the Apple Home Indicator in react-native", 5 | "main": "index.tsx", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "test-watch": "jest --watch", 9 | "tsc": "tsc", 10 | "eslint": "eslint .", 11 | "codecov": "codecov" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "Home Indicator", 16 | "prefersHomeIndicatorAutoHidden", 17 | "iphoneX", 18 | "Safe Area" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/flowkey/react-native-home-indicator" 23 | }, 24 | "author": "flowkey.com", 25 | "contributors": [ 26 | { 27 | "name": "Michael Knoch" 28 | } 29 | ], 30 | "license": "MIT", 31 | "peerDependencies": { 32 | "react-native": ">=0.41.2" 33 | }, 34 | "devDependencies": { 35 | "@react-native-community/eslint-config": "^3.0.1", 36 | "@types/react": "^17.0.44", 37 | "@types/react-native": "^0.67.6", 38 | "@typescript-eslint/eslint-plugin": "^5.22.0", 39 | "@typescript-eslint/parser": "^4.33.0", 40 | "babel-eslint": "^10.1.0", 41 | "babel-jest": "^27.2.5", 42 | "codecov": "^3.7.2", 43 | "eslint": "^7.32.0", 44 | "eslint-import-resolver-typescript": "^2.7.1", 45 | "eslint-plugin-import": "^2.25.2", 46 | "jest": "^27.2.5", 47 | "metro-react-native-babel-preset": "^0.66.2", 48 | "prettier": "^2.4.1", 49 | "react": "^17.0.2", 50 | "react-native": "^0.66.1", 51 | "react-test-renderer": "^17.0.2", 52 | "typescript": "^4.6.4" 53 | }, 54 | "files": [ 55 | "ios", 56 | "react-native-home-indicator.podspec" 57 | ], 58 | "jest": { 59 | "preset": "react-native" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /react-native-home-indicator.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'react-native-home-indicator' 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.description = package['description'] 10 | s.license = package['license'] 11 | s.author = package['author'] 12 | s.homepage = package['repository']['url'] 13 | s.source = { :git => "https://github.com/flowkey/react-native-home-indicator", :tag => "#{s.version}" } 14 | 15 | s.ios.deployment_target = "8.0" 16 | s.tvos.deployment_target = "9.0" 17 | 18 | s.source_files = "ios/**/*.{h,m}" 19 | s.dependency "React-Core" 20 | end 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "esModuleInterop": true, 6 | "isolatedModules": true, 7 | "jsx": "react-native", 8 | "lib": ["es2017"], 9 | "moduleResolution": "node", 10 | "noEmit": true, 11 | "strict": true, 12 | "skipLibCheck": true, 13 | "noEmit": true, 14 | "target": "esnext", 15 | "baseUrl": "." 16 | }, 17 | "include": ["index.tsx"], 18 | "exclude": [ 19 | "node_modules", 20 | "babel.config.js", 21 | "metro.config.js", 22 | "jest.config.js" 23 | ] 24 | } 25 | --------------------------------------------------------------------------------