diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..bd30a3c8 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,290 @@ +{ + "root": true, + + "parser": "babel-eslint", + + "env": { + "es6": true, + }, + + "plugins": [ + "eslint-comments", + "flowtype", + "prettier", + "react", + "react-hooks", + "react-native", + "jest", + ], + + // Map from global var to bool specifying if it can be redefined + "globals": { + "__DEV__": true, + "__dirname": false, + "__fbBatchedBridgeConfig": false, + "alert": false, + "cancelAnimationFrame": false, + "cancelIdleCallback": false, + "clearImmediate": true, + "clearInterval": false, + "clearTimeout": false, + "console": false, + "document": false, + "escape": false, + "Event": false, + "EventTarget": false, + "exports": false, + "fetch": false, + "FormData": false, + "global": false, + "Map": true, + "module": false, + "navigator": false, + "process": false, + "Promise": true, + "requestAnimationFrame": true, + "requestIdleCallback": true, + "require": false, + "Set": true, + "setImmediate": true, + "setInterval": false, + "setTimeout": false, + "window": false, + "XMLHttpRequest": false, + }, + + "rules": { + // General + "comma-dangle": [1, "always-multiline"], // allow or disallow trailing commas + "no-cond-assign": 1, // disallow assignment in conditional expressions + "no-console": 0, // disallow use of console (off by default in the node environment) + "no-const-assign": 2, // disallow assignment to const-declared variables + "no-constant-condition": 0, // disallow use of constant expressions in conditions + "no-control-regex": 1, // disallow control characters in regular expressions + "no-debugger": 1, // disallow use of debugger + "no-dupe-class-members": 2, // Disallow duplicate name in class members + "no-dupe-keys": 2, // disallow duplicate keys when creating object literals + "no-empty": 0, // disallow empty statements + "no-ex-assign": 1, // disallow assigning to the exception in a catch block + "no-extra-boolean-cast": 1, // disallow double-negation boolean casts in a boolean context + "no-extra-parens": 0, // disallow unnecessary parentheses (off by default) + "no-extra-semi": 1, // disallow unnecessary semicolons + "no-func-assign": 1, // disallow overwriting functions written as function declarations + "no-inner-declarations": 0, // disallow function or variable declarations in nested blocks + "no-invalid-regexp": 1, // disallow invalid regular expression strings in the RegExp constructor + "no-negated-in-lhs": 1, // disallow negation of the left operand of an in expression + "no-obj-calls": 1, // disallow the use of object properties of the global object (Math and JSON) as functions + "no-regex-spaces": 1, // disallow multiple spaces in a regular expression literal + "no-reserved-keys": 0, // disallow reserved words being used as object literal keys (off by default) + "no-sparse-arrays": 1, // disallow sparse arrays + "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement + "use-isnan": 1, // disallow comparisons with the value NaN + "valid-jsdoc": 0, // Ensure JSDoc comments are valid (off by default) + "valid-typeof": 1, // Ensure that the results of typeof are compared against a valid string + + // Best Practices + // These are rules designed to prevent you from making mistakes. They either prescribe a better way of doing something or help you avoid footguns. + + "block-scoped-var": 0, // treat var statements as if they were block scoped (off by default) + "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default) + "consistent-return": 0, // require return statements to either always or never specify values + "curly": 1, // specify curly brace conventions for all control statements + "default-case": 0, // require default case in switch statements (off by default) + "dot-notation": 1, // encourages use of dot notation whenever possible + "eqeqeq": [1, "allow-null"], // require the use of === and !== + "guard-for-in": 0, // make sure for-in loops have an if statement (off by default) + "no-alert": 1, // disallow the use of alert, confirm, and prompt + "no-caller": 1, // disallow use of arguments.caller or arguments.callee + "no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default) + "no-else-return": 0, // disallow else after a return in an if (off by default) + "no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default) + "no-eval": 2, // disallow use of eval() + "no-extend-native": 1, // disallow adding to native types + "no-extra-bind": 1, // disallow unnecessary function binding + "no-fallthrough": 1, // disallow fallthrough of case statements + "no-floating-decimal": 1, // disallow the use of leading or trailing decimal points in numeric literals (off by default) + "no-implied-eval": 1, // disallow use of eval()-like methods + "no-labels": 1, // disallow use of labeled statements + "no-iterator": 1, // disallow usage of __iterator__ property + "no-lone-blocks": 1, // disallow unnecessary nested blocks + "no-loop-func": 0, // disallow creation of functions within loops + "no-multi-str": 0, // disallow use of multiline strings + "no-native-reassign": 0, // disallow reassignments of native objects + "no-new": 1, // disallow use of new operator when not part of the assignment or comparison + "no-new-func": 2, // disallow use of new operator for Function object + "no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean + "no-octal": 1, // disallow use of octal literals + "no-octal-escape": 1, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251"; + "no-proto": 1, // disallow usage of __proto__ property + "no-redeclare": 0, // disallow declaring the same variable more then once + "no-return-assign": 1, // disallow use of assignment in return statement + "no-script-url": 1, // disallow use of javascript: urls. + "no-self-compare": 1, // disallow comparisons where both sides are exactly the same (off by default) + "no-sequences": 1, // disallow use of comma operator + "no-unused-expressions": 0, // disallow usage of expressions in statement position + "no-void": 1, // disallow use of void operator (off by default) + "no-warning-comments": 0, // disallow usage of configurable warning terms in comments": 1, // e.g. TODO or FIXME (off by default) + "no-with": 1, // disallow use of the with statement + "radix": 1, // require use of the second argument for parseInt() (off by default) + "semi-spacing": 1, // require a space after a semi-colon + "vars-on-top": 0, // requires to declare all vars on top of their containing scope (off by default) + "wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses (off by default) + "yoda": 1, // require or disallow Yoda conditions + + // Variables + // These rules have to do with variable declarations. + + "no-catch-shadow": 1, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment) + "no-delete-var": 1, // disallow deletion of variables + "no-label-var": 1, // disallow labels that share a name with a variable + "no-shadow": 1, // disallow declaration of variables already declared in the outer scope + "no-shadow-restricted-names": 1, // disallow shadowing of names such as arguments + "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block + "no-undefined": 0, // disallow use of undefined variable (off by default) + "no-undef-init": 1, // disallow use of undefined when initializing variables + "no-unused-vars": [1, {"vars": "all", "args": "none", ignoreRestSiblings: true}], // disallow declaration of variables that are not used in the code + "no-use-before-define": 0, // disallow use of variables before they are defined + + // Node.js + // These rules are specific to JavaScript running on Node.js. + + "handle-callback-err": 1, // enforces error handling in callbacks (off by default) (on by default in the node environment) + "no-mixed-requires": 1, // disallow mixing regular variable and require declarations (off by default) (on by default in the node environment) + "no-new-require": 1, // disallow use of new operator with the require function (off by default) (on by default in the node environment) + "no-path-concat": 1, // disallow string concatenation with __dirname and __filename (off by default) (on by default in the node environment) + "no-process-exit": 0, // disallow process.exit() (on by default in the node environment) + "no-restricted-modules": 1, // restrict usage of specified node modules (off by default) + "no-sync": 0, // disallow use of synchronous methods (off by default) + + // ESLint Comments Plugin + // The following rules are made available via `eslint-plugin-eslint-comments` + "eslint-comments/no-aggregating-enable": 1, // disallows eslint-enable comments for multiple eslint-disable comments + "eslint-comments/no-unlimited-disable": 1, // disallows eslint-disable comments without rule names + "eslint-comments/no-unused-disable": 1, // disallow disables that don't cover any errors + "eslint-comments/no-unused-enable": 1, // // disallow enables that don't enable anything or enable rules that weren't disabled + + // Flow Plugin + // The following rules are made available via `eslint-plugin-flowtype` + "flowtype/define-flow-type": 1, + "flowtype/use-flow-type": 1, + + // Prettier Plugin + // https://github.com/prettier/eslint-plugin-prettier + "prettier/prettier": [2, "fb", "@format"], + + // Stylistic Issues + // These rules are purely matters of style and are quite subjective. + + "key-spacing": 0, + "keyword-spacing": 1, // enforce spacing before and after keywords + "jsx-quotes": [1, "prefer-double"], // enforces the usage of double quotes for all JSX attribute values which doesn’t contain a double quote + "comma-spacing": 0, + "no-multi-spaces": 0, + "brace-style": 0, // enforce one true brace style (off by default) + "camelcase": 0, // require camel case names + "consistent-this": 1, // enforces consistent naming when capturing the current execution context (off by default) + "eol-last": 1, // enforce newline at the end of file, with no multiple empty lines + "func-names": 0, // require function expressions to have a name (off by default) + "func-style": 0, // enforces use of function declarations or expressions (off by default) + "new-cap": 0, // require a capital letter for constructors + "new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments + "no-nested-ternary": 0, // disallow nested ternary expressions (off by default) + "no-array-constructor": 1, // disallow use of the Array constructor + "no-empty-character-class": 1, // disallow the use of empty character classes in regular expressions + "no-lonely-if": 0, // disallow if as the only statement in an else block (off by default) + "no-new-object": 1, // disallow use of the Object constructor + "no-spaced-func": 1, // disallow space between function identifier and application + "no-ternary": 0, // disallow the use of ternary operators (off by default) + "no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines + "no-underscore-dangle": 0, // disallow dangling underscores in identifiers + "no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation + "quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used + "quote-props": 0, // require quotes around object literal property names (off by default) + "semi": 1, // require or disallow use of semicolons instead of ASI + "sort-vars": 0, // sort variables within the same declaration block (off by default) + "space-in-brackets": 0, // require or disallow spaces inside brackets (off by default) + "space-in-parens": 0, // require or disallow spaces inside parentheses (off by default) + "space-infix-ops": 1, // require spaces around operators + "space-unary-ops": [1, { "words": true, "nonwords": false }], // require or disallow spaces before/after unary operators (words on by default, nonwords off by default) + "max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested (off by default) + "one-var": 0, // allow just one var statement per function (off by default) + "wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default) + + // Legacy + // The following rules are included for compatibility with JSHint and JSLint. While the names of the rules may not match up with the JSHint/JSLint counterpart, the functionality is the same. + + "max-depth": 0, // specify the maximum depth that blocks can be nested (off by default) + "max-len": 0, // specify the maximum length of a line in your program (off by default) + "max-params": 0, // limits the number of parameters that can be used in the function declaration. (off by default) + "max-statements": 0, // specify the maximum number of statement allowed in a function (off by default) + "no-bitwise": 1, // disallow use of bitwise operators (off by default) + "no-plusplus": 0, // disallow use of unary operators, ++ and -- (off by default) + + // React Plugin + // The following rules are made available via `eslint-plugin-react`. + + "react/display-name": 0, + "react/jsx-boolean-value": 0, + "react/jsx-no-comment-textnodes": 1, + "react/jsx-no-duplicate-props": 2, + "react/jsx-no-undef": 2, + "react/jsx-sort-props": 0, + "react/jsx-uses-react": 1, + "react/jsx-uses-vars": 1, + "react/no-did-mount-set-state": 1, + "react/no-did-update-set-state": 1, + "react/no-multi-comp": 0, + "react/no-string-refs": 1, + "react/no-unknown-property": 0, + "react/prop-types": 0, + "react/react-in-jsx-scope": 1, + "react/self-closing-comp": 1, + "react/wrap-multilines": 0, + + // React-Hooks Plugin + // The following rules are made available via `eslint-plugin-react-hooks` + "react-hooks/rules-of-hooks": "error", + + // React-Native Plugin + // The following rules are made available via `eslint-plugin-react-native` + + "react-native/no-inline-styles": 1, + + // Jest Plugin + // The following rules are made available via `eslint-plugin-jest`. + "jest/no-disabled-tests": 1, + "jest/no-focused-tests": 1, + "jest/no-identical-title": 1, + "jest/valid-expect": 1, + }, + + "overrides": [ + { + "files": [ + "**/__fixtures__/**/*.js", + "**/__mocks__/**/*.js", + "**/__tests__/**/*.js", + "jest/**/*.js", + "RNTester/**/*.js", + ], + "globals": { + // Expose some Jest globals for test helpers + "afterAll": true, + "afterEach": true, + "beforeAll": true, + "beforeEach": true, + "expect": true, + "jest": true, + }, + }, + { + "files": [ + "**/__tests__/**/*-test.js", + ], + "env": { + "jasmine": true, + "jest": true, + }, + }, + ], +} \ No newline at end of file diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 00000000..7a7cd225 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,90 @@ +[ignore] +; This flowconfig is forked by platform - the only difference between them is which suffix is ignored. +.*/*[.]android.js +;.*/*[.]ios.js + +; Ignore templates for 'react-native init' +.*/local-cli/templates/.* + +; Ignore the Dangerfile +node_modules/react-native/bots/dangerfile.js + +; Ignore "BUCK" generated dirs +node_modules/react-native/\.buckd/ + +; Ignore unexpected extra "@providesModule" +.*/node_modules/.*/node_modules/fbjs/.* + +; Ignore duplicate module providers +; For RN Apps installed via npm, "Libraries" folder is inside +; "node_modules/react-native" but in the source repo it is in the root +.*/Libraries/react-native/React.js + +; Ignore polyfills +.*/Libraries/polyfills/.* + +; Ignore metro +.*/node_modules/metro/.* + +; Ignore "config-chain"'s test folder - it has a corrupt JSON file that's tripping flow +.*/node_modules/config-chain/test/*. + +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/invariant') +.*/node_modules/invariant/.* +.*/node_modules/warning/.* + +[include] + +[libs] +node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow/ +node_modules/react-native/flow-github/ + +[lints] + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +module.system=haste +module.system.haste.use_name_reducers=true +# keep the following in sync with server/haste/hasteImpl.js +# get basename +module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' +# strip .js or .js.flow suffix +module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' +# strip platform suffix +module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' +module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' +module.system.haste.paths.blacklist=.*/__tests__/.* +module.system.haste.paths.blacklist=.*/__mocks__/.* +module.system.haste.paths.whitelist=/js/.* +module.system.haste.paths.whitelist=/node_modules/react-native/Libraries/.* +module.system.haste.paths.whitelist=/node_modules/react-native/RNTester/.* +module.system.haste.paths.whitelist=/node_modules/react-native/IntegrationTests/.* +module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/Animated/src/polyfills/.* + +munge_underscores=true + +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' +# Support the library import in examples +module.name_mapper='^\@react-native-community/async-storage$' -> '/lib/AsyncStorage.js' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*[react_native\\(_android\\)?_oss|react_native\\(_android\\)?_fb][a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError + +[strict] + +[version] +^0.86.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..95367758 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ + +# OSX +# +.DS_Store + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml + +# BUCK +buck-out/ +\.buckd/ +*.keystore + +# Editor config +.vscode \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..9b128286 --- /dev/null +++ b/.npmignore @@ -0,0 +1,85 @@ +# JS +node_modules +yarn.lock + +# Project files +CONTRIBUTING.md +CODE_OF_CONDUCT.md +README.md + +# Config files +.babelrc +babel.config.js +.editorconfig +.eslintrc +.flowconfig +.watchmanconfig +jsconfig.json +.npmrc +.gitattributes +.circleci +*.coverage.json +.opensource +.circleci +.eslintignore +codecov.yml + +# Example +example/ + +# Android +android/*/build/ +android/gradlew +android/build +android/gradlew.bat +android/gradle/ +android/com_crashlytics_export_strings.xml +android/local.properties +android/.gradle/ +android/.signing/ +android/.idea/gradle.xml +android/.idea/libraries/ +android/.idea/workspace.xml +android/.idea/tasks.xml +android/.idea/.name +android/.idea/compiler.xml +android/.idea/copyright/profiles_settings.xml +android/.idea/encodings.xml +android/.idea/misc.xml +android/.idea/modules.xml +android/.idea/scopes/scope_settings.xml +android/.idea/vcs.xml +android/*.iml +android/.settings + +# iOS +ios/*.xcodeproj/xcuserdata +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 +*.xcuserstate +project.xcworkspace/ +xcuserdata/ + +# Misc +.DS_Store +.DS_Store? +*.DS_Store +coverage.android.json +coverage.ios.json +coverage +npm-debug.log +.github +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.dbandroid/gradle +docs +.idea +tests/ +bin/test.js +codorials +.vscode +.nyc_output \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..1d4c3eff --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "requirePragma": true, + "singleQuote": true, + "trailingComma": "all", + "bracketSpacing": false, + "jsxBracketSameLine": true, + "parser": "flow" +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d9021534 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 4bb8f7d8..0547f860 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ # react-native-async-storage + +Asynchronous, persistent, key-value storage system for React Native. + +## Getting started + + +### Install + +`yarn add @react-native-community/async-storage` + +or + +`npm install @react-native-community/async-storage --save` + + +### Link + +`react-native link @react-native-community/async-storage` + +## Usage + +ToDo + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 00000000..436e8dec --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,40 @@ + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} + +def getExtOrDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['RNAsyncStorage_' + name] +} + +def getExtOrIntegerDefault(name) { + return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['RNAsyncStorage_' + name]).toInteger() +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') + buildToolsVersion getExtOrDefault('buildToolsVersion') + + defaultConfig { + minSdkVersion getExtOrIntegerDefault('minSdkVersion') + targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') + } +} + +repositories { + mavenCentral() +} + +dependencies { + api 'com.facebook.react:react-native:+' +} + \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..109465ba --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +RNAsyncStorage_compileSdkVersion=28 +RNAsyncStorage_buildToolsVersion=28.0.3 +RNAsyncStorage_targetSdkVersion=28 +RNAsyncStorage_minSdkVersion=19 \ No newline at end of file diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..7e180bd3 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncLocalStorageUtil.java b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncLocalStorageUtil.java new file mode 100644 index 00000000..fe29a269 --- /dev/null +++ b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncLocalStorageUtil.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnativecommunity.asyncstorage; + +import javax.annotation.Nullable; + +import java.util.Arrays; +import java.util.Iterator; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.text.TextUtils; + +import com.facebook.react.bridge.ReadableArray; + +import org.json.JSONException; +import org.json.JSONObject; + +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.KEY_COLUMN; +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.TABLE_CATALYST; +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.VALUE_COLUMN; + +/** + * Helper for database operations. + */ +public class AsyncLocalStorageUtil { + + /** + * Build the String required for an SQL select statement: + * WHERE key IN (?, ?, ..., ?) + * without 'WHERE' and with selectionCount '?' + */ + /* package */ static String buildKeySelection(int selectionCount) { + String[] list = new String[selectionCount]; + Arrays.fill(list, "?"); + return KEY_COLUMN + " IN (" + TextUtils.join(", ", list) + ")"; + } + + /** + * Build the String[] arguments needed for an SQL selection, i.e.: + * {a, b, c} + * to be used in the SQL select statement: WHERE key in (?, ?, ?) + */ + /* package */ static String[] buildKeySelectionArgs(ReadableArray keys, int start, int count) { + String[] selectionArgs = new String[count]; + for (int keyIndex = 0; keyIndex < count; keyIndex++) { + selectionArgs[keyIndex] = keys.getString(start + keyIndex); + } + return selectionArgs; + } + + /** + * Returns the value of the given key, or null if not found. + */ + public static @Nullable String getItemImpl(SQLiteDatabase db, String key) { + String[] columns = {VALUE_COLUMN}; + String[] selectionArgs = {key}; + + Cursor cursor = db.query( + TABLE_CATALYST, + columns, + KEY_COLUMN + "=?", + selectionArgs, + null, + null, + null); + + try { + if (!cursor.moveToFirst()) { + return null; + } else { + return cursor.getString(0); + } + } finally { + cursor.close(); + } + } + + /** + * Sets the value for the key given, returns true if successful, false otherwise. + */ + /* package */ static boolean setItemImpl(SQLiteDatabase db, String key, String value) { + ContentValues contentValues = new ContentValues(); + contentValues.put(KEY_COLUMN, key); + contentValues.put(VALUE_COLUMN, value); + + long inserted = db.insertWithOnConflict( + TABLE_CATALYST, + null, + contentValues, + SQLiteDatabase.CONFLICT_REPLACE); + + return (-1 != inserted); + } + + /** + * Does the actual merge of the (key, value) pair with the value stored in the database. + * NB: This assumes that a database lock is already in effect! + * @return the errorCode of the operation + */ + /* package */ static boolean mergeImpl(SQLiteDatabase db, String key, String value) + throws JSONException { + String oldValue = getItemImpl(db, key); + String newValue; + + if (oldValue == null) { + newValue = value; + } else { + JSONObject oldJSON = new JSONObject(oldValue); + JSONObject newJSON = new JSONObject(value); + deepMergeInto(oldJSON, newJSON); + newValue = oldJSON.toString(); + } + + return setItemImpl(db, key, newValue); + } + + /** + * Merges two {@link JSONObject}s. The newJSON object will be merged with the oldJSON object by + * either overriding its values, or merging them (if the values of the same key in both objects + * are of type {@link JSONObject}). oldJSON will contain the result of this merge. + */ + private static void deepMergeInto(JSONObject oldJSON, JSONObject newJSON) + throws JSONException { + Iterator keys = newJSON.keys(); + while (keys.hasNext()) { + String key = (String) keys.next(); + + JSONObject newJSONObject = newJSON.optJSONObject(key); + JSONObject oldJSONObject = oldJSON.optJSONObject(key); + if (newJSONObject != null && oldJSONObject != null) { + deepMergeInto(oldJSONObject, newJSONObject); + oldJSON.put(key, oldJSONObject); + } else { + oldJSON.put(key, newJSON.get(key)); + } + } + } +} diff --git a/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageErrorUtil.java b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageErrorUtil.java new file mode 100644 index 00000000..d74a0f11 --- /dev/null +++ b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageErrorUtil.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnativecommunity.asyncstorage; + +import javax.annotation.Nullable; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; + +/** + * Helper class for database errors. + */ +public class AsyncStorageErrorUtil { + + /** + * Create Error object to be passed back to the JS callback. + */ + /* package */ static WritableMap getError(@Nullable String key, String errorMessage) { + WritableMap errorMap = Arguments.createMap(); + errorMap.putString("message", errorMessage); + if (key != null) { + errorMap.putString("key", key); + } + return errorMap; + } + + /* package */ static WritableMap getInvalidKeyError(@Nullable String key) { + return getError(key, "Invalid key"); + } + + /* package */ static WritableMap getInvalidValueError(@Nullable String key) { + return getError(key, "Invalid Value"); + } + + /* package */ static WritableMap getDBError(@Nullable String key) { + return getError(key, "Database Error"); + } + + +} diff --git a/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageModule.java b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageModule.java new file mode 100644 index 00000000..211fe8a4 --- /dev/null +++ b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageModule.java @@ -0,0 +1,435 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnativecommunity.asyncstorage; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; +import android.os.AsyncTask; + +import com.facebook.common.logging.FLog; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.GuardedAsyncTask; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.modules.common.ModuleDataCleaner; + +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.concurrent.Executor; + +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.KEY_COLUMN; +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.TABLE_CATALYST; +import static com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.VALUE_COLUMN; + +@ReactModule(name = AsyncStorageModule.NAME) +public final class AsyncStorageModule + extends ReactContextBaseJavaModule implements ModuleDataCleaner.Cleanable { + + // changed name to not conflict with AsyncStorage from RN repo + public static final String NAME = "RNC_AsyncSQLiteDBStorage"; + + // SQL variable number limit, defined by SQLITE_LIMIT_VARIABLE_NUMBER: + // https://raw.githubusercontent.com/android/platform_external_sqlite/master/dist/sqlite3.c + private static final int MAX_SQL_KEYS = 999; + + private ReactDatabaseSupplier mReactDatabaseSupplier; + private boolean mShuttingDown = false; + + // Adapted from https://android.googlesource.com/platform/frameworks/base.git/+/1488a3a19d4681a41fb45570c15e14d99db1cb66/core/java/android/os/AsyncTask.java#237 + private class SerialExecutor implements Executor { + private final ArrayDeque mTasks = new ArrayDeque(); + private Runnable mActive; + private final Executor executor; + + SerialExecutor(Executor executor) { + this.executor = executor; + } + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + executor.execute(mActive); + } + } + } + + private final SerialExecutor executor; + + public AsyncStorageModule(ReactApplicationContext reactContext) { + this(reactContext, AsyncTask.THREAD_POOL_EXECUTOR); + } + + @VisibleForTesting + AsyncStorageModule(ReactApplicationContext reactContext, Executor executor) { + super(reactContext); + this.executor = new SerialExecutor(executor); + mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(reactContext); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public void initialize() { + super.initialize(); + mShuttingDown = false; + } + + @Override + public void onCatalystInstanceDestroy() { + mShuttingDown = true; + } + + @Override + public void clearSensitiveData() { + // Clear local storage. If fails, crash, since the app is potentially in a bad state and could + // cause a privacy violation. We're still not recovering from this well, but at least the error + // will be reported to the server. + mReactDatabaseSupplier.clearAndCloseDatabase(); + } + + /** + * Given an array of keys, this returns a map of (key, value) pairs for the keys found, and + * (key, null) for the keys that haven't been found. + */ + @ReactMethod + public void multiGet(final ReadableArray keys, final Callback callback) { + if (keys == null) { + callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null), null); + return; + } + + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null), null); + return; + } + + String[] columns = {KEY_COLUMN, VALUE_COLUMN}; + HashSet keysRemaining = new HashSet<>(); + WritableArray data = Arguments.createArray(); + for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) { + int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS); + Cursor cursor = mReactDatabaseSupplier.get().query( + TABLE_CATALYST, + columns, + AsyncLocalStorageUtil.buildKeySelection(keyCount), + AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount), + null, + null, + null); + keysRemaining.clear(); + try { + if (cursor.getCount() != keys.size()) { + // some keys have not been found - insert them with null into the final array + for (int keyIndex = keyStart; keyIndex < keyStart + keyCount; keyIndex++) { + keysRemaining.add(keys.getString(keyIndex)); + } + } + + if (cursor.moveToFirst()) { + do { + WritableArray row = Arguments.createArray(); + row.pushString(cursor.getString(0)); + row.pushString(cursor.getString(1)); + data.pushArray(row); + keysRemaining.remove(cursor.getString(0)); + } while (cursor.moveToNext()); + } + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null); + return; + } finally { + cursor.close(); + } + + for (String key : keysRemaining) { + WritableArray row = Arguments.createArray(); + row.pushString(key); + row.pushNull(); + data.pushArray(row); + } + keysRemaining.clear(); + } + + callback.invoke(null, data); + } + }.executeOnExecutor(executor); + } + + /** + * Inserts multiple (key, value) pairs. If one or more of the pairs cannot be inserted, this will + * return AsyncLocalStorageFailure, but all other pairs will have been inserted. + * The insertion will replace conflicting (key, value) pairs. + */ + @ReactMethod + public void multiSet(final ReadableArray keyValueArray, final Callback callback) { + if (keyValueArray.size() == 0) { + callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null)); + return; + } + + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null)); + return; + } + + String sql = "INSERT OR REPLACE INTO " + TABLE_CATALYST + " VALUES (?, ?);"; + SQLiteStatement statement = mReactDatabaseSupplier.get().compileStatement(sql); + WritableMap error = null; + try { + mReactDatabaseSupplier.get().beginTransaction(); + for (int idx=0; idx < keyValueArray.size(); idx++) { + if (keyValueArray.getArray(idx).size() != 2) { + error = AsyncStorageErrorUtil.getInvalidValueError(null); + return; + } + if (keyValueArray.getArray(idx).getString(0) == null) { + error = AsyncStorageErrorUtil.getInvalidKeyError(null); + return; + } + if (keyValueArray.getArray(idx).getString(1) == null) { + error = AsyncStorageErrorUtil.getInvalidValueError(null); + return; + } + + statement.clearBindings(); + statement.bindString(1, keyValueArray.getArray(idx).getString(0)); + statement.bindString(2, keyValueArray.getArray(idx).getString(1)); + statement.execute(); + } + mReactDatabaseSupplier.get().setTransactionSuccessful(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } finally { + try { + mReactDatabaseSupplier.get().endTransaction(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + if (error == null) { + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } + } + } + if (error != null) { + callback.invoke(error); + } else { + callback.invoke(); + } + } + }.executeOnExecutor(executor); + } + + /** + * Removes all rows of the keys given. + */ + @ReactMethod + public void multiRemove(final ReadableArray keys, final Callback callback) { + if (keys.size() == 0) { + callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null)); + return; + } + + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null)); + return; + } + + WritableMap error = null; + try { + mReactDatabaseSupplier.get().beginTransaction(); + for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) { + int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS); + mReactDatabaseSupplier.get().delete( + TABLE_CATALYST, + AsyncLocalStorageUtil.buildKeySelection(keyCount), + AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount)); + } + mReactDatabaseSupplier.get().setTransactionSuccessful(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } finally { + try { + mReactDatabaseSupplier.get().endTransaction(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + if (error == null) { + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } + } + } + if (error != null) { + callback.invoke(error); + } else { + callback.invoke(); + } + } + }.executeOnExecutor(executor); + } + + /** + * Given an array of (key, value) pairs, this will merge the given values with the stored values + * of the given keys, if they exist. + */ + @ReactMethod + public void multiMerge(final ReadableArray keyValueArray, final Callback callback) { + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null)); + return; + } + WritableMap error = null; + try { + mReactDatabaseSupplier.get().beginTransaction(); + for (int idx = 0; idx < keyValueArray.size(); idx++) { + if (keyValueArray.getArray(idx).size() != 2) { + error = AsyncStorageErrorUtil.getInvalidValueError(null); + return; + } + + if (keyValueArray.getArray(idx).getString(0) == null) { + error = AsyncStorageErrorUtil.getInvalidKeyError(null); + return; + } + + if (keyValueArray.getArray(idx).getString(1) == null) { + error = AsyncStorageErrorUtil.getInvalidValueError(null); + return; + } + + if (!AsyncLocalStorageUtil.mergeImpl( + mReactDatabaseSupplier.get(), + keyValueArray.getArray(idx).getString(0), + keyValueArray.getArray(idx).getString(1))) { + error = AsyncStorageErrorUtil.getDBError(null); + return; + } + } + mReactDatabaseSupplier.get().setTransactionSuccessful(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } finally { + try { + mReactDatabaseSupplier.get().endTransaction(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + if (error == null) { + error = AsyncStorageErrorUtil.getError(null, e.getMessage()); + } + } + } + if (error != null) { + callback.invoke(error); + } else { + callback.invoke(); + } + } + }.executeOnExecutor(executor); + } + + /** + * Clears the database. + */ + @ReactMethod + public void clear(final Callback callback) { + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!mReactDatabaseSupplier.ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null)); + return; + } + try { + mReactDatabaseSupplier.clear(); + callback.invoke(); + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage())); + } + } + }.executeOnExecutor(executor); + } + + /** + * Returns an array with all keys from the database. + */ + @ReactMethod + public void getAllKeys(final Callback callback) { + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + if (!ensureDatabase()) { + callback.invoke(AsyncStorageErrorUtil.getDBError(null), null); + return; + } + WritableArray data = Arguments.createArray(); + String[] columns = {KEY_COLUMN}; + Cursor cursor = mReactDatabaseSupplier.get() + .query(TABLE_CATALYST, columns, null, null, null, null, null); + try { + if (cursor.moveToFirst()) { + do { + data.pushString(cursor.getString(0)); + } while (cursor.moveToNext()); + } + } catch (Exception e) { + FLog.w(ReactConstants.TAG, e.getMessage(), e); + callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null); + return; + } finally { + cursor.close(); + } + callback.invoke(null, data); + } + }.executeOnExecutor(executor); + } + + /** + * Verify the database is open for reads and writes. + */ + private boolean ensureDatabase() { + return !mShuttingDown && mReactDatabaseSupplier.ensureDatabase(); + } +} diff --git a/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStoragePackage.java b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStoragePackage.java new file mode 100644 index 00000000..25eb5a14 --- /dev/null +++ b/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStoragePackage.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnativecommunity.asyncstorage; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class AsyncStoragePackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new AsyncStorageModule(reactContext)); + } + + // Deprecated in RN 0.47 + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + @SuppressWarnings("rawtypes") + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/android/src/main/java/com/reactnativecommunity/asyncstorage/ReactDatabaseSupplier.java b/android/src/main/java/com/reactnativecommunity/asyncstorage/ReactDatabaseSupplier.java new file mode 100644 index 00000000..9f992ca4 --- /dev/null +++ b/android/src/main/java/com/reactnativecommunity/asyncstorage/ReactDatabaseSupplier.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.reactnativecommunity.asyncstorage; + +import javax.annotation.Nullable; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteOpenHelper; + +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; + +/** + * Database supplier of the database used by react native. This creates, opens and deletes the + * database as necessary. + */ +public class ReactDatabaseSupplier extends SQLiteOpenHelper { + + // VisibleForTesting + public static final String DATABASE_NAME = "RKStorage"; + + private static final int DATABASE_VERSION = 1; + private static final int SLEEP_TIME_MS = 30; + + static final String TABLE_CATALYST = "catalystLocalStorage"; + static final String KEY_COLUMN = "key"; + static final String VALUE_COLUMN = "value"; + + static final String VERSION_TABLE_CREATE = + "CREATE TABLE " + TABLE_CATALYST + " (" + + KEY_COLUMN + " TEXT PRIMARY KEY, " + + VALUE_COLUMN + " TEXT NOT NULL" + + ")"; + + private static @Nullable ReactDatabaseSupplier sReactDatabaseSupplierInstance; + + private Context mContext; + private @Nullable SQLiteDatabase mDb; + private long mMaximumDatabaseSize = 6L * 1024L * 1024L; // 6 MB in bytes + + private ReactDatabaseSupplier(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + mContext = context; + } + + public static ReactDatabaseSupplier getInstance(Context context) { + if (sReactDatabaseSupplierInstance == null) { + sReactDatabaseSupplierInstance = new ReactDatabaseSupplier(context.getApplicationContext()); + } + return sReactDatabaseSupplierInstance; + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(VERSION_TABLE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion != newVersion) { + deleteDatabase(); + onCreate(db); + } + } + + /** + * Verify the database exists and is open. + */ + /* package */ synchronized boolean ensureDatabase() { + if (mDb != null && mDb.isOpen()) { + return true; + } + // Sometimes retrieving the database fails. We do 2 retries: first without database deletion + // and then with deletion. + SQLiteException lastSQLiteException = null; + for (int tries = 0; tries < 2; tries++) { + try { + if (tries > 0) { + deleteDatabase(); + } + mDb = getWritableDatabase(); + break; + } catch (SQLiteException e) { + lastSQLiteException = e; + } + // Wait before retrying. + try { + Thread.sleep(SLEEP_TIME_MS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + if (mDb == null) { + throw lastSQLiteException; + } + // This is a sane limit to protect the user from the app storing too much data in the database. + // This also protects the database from filling up the disk cache and becoming malformed + // (endTransaction() calls will throw an exception, not rollback, and leave the db malformed). + mDb.setMaximumSize(mMaximumDatabaseSize); + return true; + } + + /** + * Create and/or open the database. + */ + public synchronized SQLiteDatabase get() { + ensureDatabase(); + return mDb; + } + + public synchronized void clearAndCloseDatabase() throws RuntimeException { + try { + clear(); + closeDatabase(); + FLog.d(ReactConstants.TAG, "Cleaned " + DATABASE_NAME); + } catch (Exception e) { + // Clearing the database has failed, delete it instead. + if (deleteDatabase()) { + FLog.d(ReactConstants.TAG, "Deleted Local Database " + DATABASE_NAME); + return; + } + // Everything failed, throw + throw new RuntimeException("Clearing and deleting database " + DATABASE_NAME + " failed"); + } + } + + /* package */ synchronized void clear() { + get().delete(TABLE_CATALYST, null, null); + } + + /** + * Sets the maximum size the database will grow to. The maximum size cannot + * be set below the current size. + */ + public synchronized void setMaximumSize(long size) { + mMaximumDatabaseSize = size; + if (mDb != null) { + mDb.setMaximumSize(mMaximumDatabaseSize); + } + } + + private synchronized boolean deleteDatabase() { + closeDatabase(); + return mContext.deleteDatabase(DATABASE_NAME); + } + + private synchronized void closeDatabase() { + if (mDb != null && mDb.isOpen()) { + mDb.close(); + mDb = null; + } + } + + // For testing purposes only! + public static void deleteInstance() { + sReactDatabaseSupplierInstance = null; + } +} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..3cdb4dfb --- /dev/null +++ b/babel.config.js @@ -0,0 +1,14 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + alias: { + '@react-native-community/asyns-storage': './lib/AsyncStorage', + }, + cwd: 'babelrc', + }, + ], + ], +}; diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 00000000..5d647565 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,56 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle diff --git a/example/__tests__/App.js b/example/__tests__/App.js new file mode 100644 index 00000000..a79ec3d5 --- /dev/null +++ b/example/__tests__/App.js @@ -0,0 +1,15 @@ +/** + * @format + * @lint-ignore-every XPLATJSCOPYRIGHT1 + */ + +import 'react-native'; +import React from 'react'; +import App from '../App'; + +// Note: test renderer must be required after react-native. +import renderer from 'react-test-renderer'; + +it('renders correctly', () => { + renderer.create(); +}); diff --git a/example/android/app/BUCK b/example/android/app/BUCK new file mode 100644 index 00000000..6a95aeb0 --- /dev/null +++ b/example/android/app/BUCK @@ -0,0 +1,55 @@ +# To learn about Buck see [Docs](https://buckbuild.com/). +# To run your application with Buck: +# - install Buck +# - `npm start` - to start the packager +# - `cd android` +# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` +# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck +# - `buck install -r android/app` - compile, install and run application +# + +load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") + +lib_deps = [] + +create_aar_targets(glob(["libs/*.aar"])) + +create_jar_targets(glob(["libs/*.jar"])) + +android_library( + name = "all-libs", + exported_deps = lib_deps, +) + +android_library( + name = "app-code", + srcs = glob([ + "src/main/java/**/*.java", + ]), + deps = [ + ":all-libs", + ":build_config", + ":res", + ], +) + +android_build_config( + name = "build_config", + package = "com.asyncstorageexample", +) + +android_resource( + name = "res", + package = "com.asyncstorageexample", + res = "src/main/res", +) + +android_binary( + name = "app", + keystore = "//android/keystores:debug", + manifest = "src/main/AndroidManifest.xml", + package_type = "debug", + deps = [ + ":app-code", + ], +) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle new file mode 100644 index 00000000..5af21ec5 --- /dev/null +++ b/example/android/app/build.gradle @@ -0,0 +1,147 @@ +apply plugin: "com.android.application" + +import com.android.build.OutputFile + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "../../node_modules/react-native/react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation + * entryFile: "index.android.js", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // whether to disable dev mode in custom build variants (by default only disabled in release) + * // for example: to disable dev mode in the staging build type (if configured) + * devDisabledInStaging: true, + * // The configuration property can be in the following formats + * // 'devDisabledIn${productFlavor}${buildType}' + * // 'devDisabledIn${buildType}' + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"], + * + * // override which node gets called and with what additional arguments + * nodeExecutableAndArgs: ["node"], + * + * // supply additional arguments to the packager + * extraPackagerArgs: [] + * ] + */ + +project.ext.react = [ + entryFile: "index.js" +] + +apply from: "../../../node_modules/react-native/react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = false + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + + defaultConfig { + applicationId "com.asyncstorageexample" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include "armeabi-v7a", "x86", "arm64-v8a" + } + } + buildTypes { + release { + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits + def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + } + } + } +} + +dependencies { + implementation project(':rnAsyncStorage') + implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" + implementation "com.facebook.react:react-native:+" // From node_modules +} + +// Run this once to be able to run the application with BUCK +// puts all compile dependencies into folder libs for BUCK to use +task copyDownloadableDepsToLibs(type: Copy) { + from configurations.compile + into 'libs' +} diff --git a/example/android/app/build_defs.bzl b/example/android/app/build_defs.bzl new file mode 100644 index 00000000..fff270f8 --- /dev/null +++ b/example/android/app/build_defs.bzl @@ -0,0 +1,19 @@ +"""Helper definitions to glob .aar and .jar targets""" + +def create_aar_targets(aarfiles): + for aarfile in aarfiles: + name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] + lib_deps.append(":" + name) + android_prebuilt_aar( + name = name, + aar = aarfile, + ) + +def create_jar_targets(jarfiles): + for jarfile in jarfiles: + name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] + lib_deps.append(":" + name) + prebuilt_jar( + name = name, + binary_jar = jarfile, + ) diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro new file mode 100644 index 00000000..a92fa177 --- /dev/null +++ b/example/android/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..12c72725 --- /dev/null +++ b/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/java/com/asyncstorageexample/MainActivity.java b/example/android/app/src/main/java/com/asyncstorageexample/MainActivity.java new file mode 100644 index 00000000..8f093117 --- /dev/null +++ b/example/android/app/src/main/java/com/asyncstorageexample/MainActivity.java @@ -0,0 +1,15 @@ +package com.asyncstorageexample; + +import com.facebook.react.ReactActivity; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "AsyncStorageExample"; + } +} diff --git a/example/android/app/src/main/java/com/asyncstorageexample/MainApplication.java b/example/android/app/src/main/java/com/asyncstorageexample/MainApplication.java new file mode 100644 index 00000000..2a0f8e77 --- /dev/null +++ b/example/android/app/src/main/java/com/asyncstorageexample/MainApplication.java @@ -0,0 +1,47 @@ +package com.asyncstorageexample; + +import android.app.Application; + +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.shell.MainReactPackage; +import com.facebook.soloader.SoLoader; +import com.reactnativecommunity.asyncstorage.AsyncStoragePackage; + +import java.util.Arrays; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new AsyncStoragePackage() + ); + } + + @Override + protected String getJSMainModuleName() { + return "example/index"; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + } +} diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..a2f59082 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..1b523998 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..ff10afd6 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..115a4c76 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..dcd3cd80 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..459ca609 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..8ca12fe0 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..8e19b410 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..b824ebdd Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..4c19a13c Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/example/android/app/src/main/res/values/strings.xml b/example/android/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..a9f943c1 --- /dev/null +++ b/example/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + AsyncStorageExample + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..319eb0ca --- /dev/null +++ b/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle new file mode 100644 index 00000000..f84862ff --- /dev/null +++ b/example/android/build.gradle @@ -0,0 +1,39 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + buildToolsVersion = "28.0.3" + minSdkVersion = 16 + compileSdkVersion = 28 + targetSdkVersion = 27 + supportLibVersion = "28.0.0" + } + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + mavenLocal() + google() + jcenter() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$rootDir/../../node_modules/react-native/android" + } + } +} + + +task wrapper(type: Wrapper) { + gradleVersion = '4.7' + distributionUrl = distributionUrl.replace("bin", "all") +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties new file mode 100644 index 00000000..89e0d99e --- /dev/null +++ b/example/android/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..01b8bf6b Binary files /dev/null and b/example/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..73bb13d5 --- /dev/null +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip diff --git a/example/android/gradlew b/example/android/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/example/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/example/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/example/android/keystores/BUCK b/example/android/keystores/BUCK new file mode 100644 index 00000000..88e4c31b --- /dev/null +++ b/example/android/keystores/BUCK @@ -0,0 +1,8 @@ +keystore( + name = "debug", + properties = "debug.keystore.properties", + store = "debug.keystore", + visibility = [ + "PUBLIC", + ], +) diff --git a/example/android/keystores/debug.keystore.properties b/example/android/keystores/debug.keystore.properties new file mode 100644 index 00000000..121bfb49 --- /dev/null +++ b/example/android/keystores/debug.keystore.properties @@ -0,0 +1,4 @@ +key.store=debug.keystore +key.alias=androiddebugkey +key.store.password=android +key.alias.password=android diff --git a/example/android/settings.gradle b/example/android/settings.gradle new file mode 100644 index 00000000..1d2109a8 --- /dev/null +++ b/example/android/settings.gradle @@ -0,0 +1,6 @@ +rootProject.name = 'AsyncStorageExample' + +include ':app' +include ':rnAsyncStorage' + +project(':rnAsyncStorage').projectDir = new File(rootProject.projectDir, '../../android') diff --git a/example/app.json b/example/app.json new file mode 100644 index 00000000..de5021de --- /dev/null +++ b/example/app.json @@ -0,0 +1,4 @@ +{ + "name": "AsyncStorageExample", + "displayName": "AsyncStorageExample" +} \ No newline at end of file diff --git a/example/index.js b/example/index.js new file mode 100644 index 00000000..073d1aa1 --- /dev/null +++ b/example/index.js @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +import {AppRegistry} from 'react-native'; +import App from './src/App'; +import {name as appName} from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/example/ios/AsyncStorageExample.xcodeproj/project.pbxproj b/example/ios/AsyncStorageExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..8ed20ab3 --- /dev/null +++ b/example/ios/AsyncStorageExample.xcodeproj/project.pbxproj @@ -0,0 +1,1128 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; + 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; + ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED297162215061F000B7C4FE /* JavaScriptCore.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTActionSheet; + }; + 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTGeolocation; + }; + 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTImage; + }; + 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B511DB1A9E6C8500147676; + remoteInfo = RCTNetwork; + }; + 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTVibration; + }; + 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTSettings; + }; + 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3C86DF461ADF2C930047B81A; + remoteInfo = RCTWebSocket; + }; + 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; + remoteInfo = React; + }; + 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ADD01A681E09402E00F6D226; + remoteInfo = "RCTBlob-tvOS"; + }; + 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; + remoteInfo = fishhook; + }; + 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32; + remoteInfo = "fishhook-tvOS"; + }; + 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EBF21BDC1FC498900052F4D5; + remoteInfo = jsinspector; + }; + 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5; + remoteInfo = "jsinspector-tvOS"; + }; + 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7; + remoteInfo = "third-party"; + }; + 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D383D3C1EBD27B6005632C8; + remoteInfo = "third-party-tvOS"; + }; + 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 139D7E881E25C6D100323FB7; + remoteInfo = "double-conversion"; + }; + 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D383D621EBD27B9005632C8; + remoteInfo = "double-conversion-tvOS"; + }; + 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A283A1D9B042B00D4039D; + remoteInfo = "RCTImage-tvOS"; + }; + 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28471D9B043800D4039D; + remoteInfo = "RCTLinking-tvOS"; + }; + 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28541D9B044C00D4039D; + remoteInfo = "RCTNetwork-tvOS"; + }; + 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28611D9B046600D4039D; + remoteInfo = "RCTSettings-tvOS"; + }; + 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A287B1D9B048500D4039D; + remoteInfo = "RCTText-tvOS"; + }; + 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28881D9B049200D4039D; + remoteInfo = "RCTWebSocket-tvOS"; + }; + 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28131D9B038B00D4039D; + remoteInfo = "React-tvOS"; + }; + 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D3C059A1DE3340900C268FA; + remoteInfo = yoga; + }; + 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D3C06751DE3340C00C268FA; + remoteInfo = "yoga-tvOS"; + }; + 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4; + remoteInfo = cxxreact; + }; + 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; + remoteInfo = "cxxreact-tvOS"; + }; + 3DC53982220F2C940035D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8; + remoteInfo = jsi; + }; + 3DC53984220F2C940035D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EDEBC73B214B45A300DD5AC8; + remoteInfo = jsiexecutor; + }; + 3DC53986220F2C940035D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ED296FB6214C9A0900B7C4FE; + remoteInfo = "jsi-tvOS"; + }; + 3DC53988220F2C940035D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = ED296FEE214C9CF800B7C4FE; + remoteInfo = "jsiexecutor-tvOS"; + }; + 3DC5398B220F2C940035D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3DC5395A220F2C940035D3A3 /* RNCAsyncstorage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RNCAsyncstorage; + }; + 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTAnimation; + }; + 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28201D9B03D100D4039D; + remoteInfo = "RCTAnimation-tvOS"; + }; + 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTLinking; + }; + 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5119B1A9E6C1200147676; + remoteInfo = RCTText; + }; + ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 358F4ED71D1E81A9004DF814; + remoteInfo = RCTBlob; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* AsyncStorageExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AsyncStorageExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = AsyncStorageExample/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = AsyncStorageExample/AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AsyncStorageExample/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = AsyncStorageExample/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = AsyncStorageExample/main.m; sourceTree = ""; }; + 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DC5395A220F2C940035D3A3 /* RNCAsyncstorage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNCAsyncstorage.xcodeproj; path = ../../ios/RNCAsyncstorage.xcodeproj; sourceTree = ""; }; + 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */, + ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, + 11D1A2F320CAFA9E000508D9 /* libRCTAnimation.a in Frameworks */, + 146834051AC3E58100842450 /* libReact.a in Frameworks */, + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00C302A81ABCB8CE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302B61ABCB90400DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302BC1ABCB91800DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, + 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302D41ABCB9D200DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, + 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302E01ABCB9EE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, + ); + name = Products; + sourceTree = ""; + }; + 139105B71AF99BAD00B5F7CC /* Products */ = { + isa = PBXGroup; + children = ( + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, + 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 139FDEE71B06529A00C62182 /* Products */ = { + isa = PBXGroup; + children = ( + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, + 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */, + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* AsyncStorageExample */ = { + isa = PBXGroup; + children = ( + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = AsyncStorageExample; + sourceTree = ""; + }; + 146834001AC3E56700842450 /* Products */ = { + isa = PBXGroup; + children = ( + 146834041AC3E56700842450 /* libReact.a */, + 3DAD3EA31DF850E9000B6D8A /* libReact.a */, + 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, + 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, + 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, + 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, + 2DF0FFDF2056DD460020B375 /* libjsinspector.a */, + 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */, + 2DF0FFE32056DD460020B375 /* libthird-party.a */, + 2DF0FFE52056DD460020B375 /* libthird-party.a */, + 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */, + 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */, + 3DC53983220F2C940035D3A3 /* libjsi.a */, + 3DC53985220F2C940035D3A3 /* libjsiexecutor.a */, + 3DC53987220F2C940035D3A3 /* libjsi-tvOS.a */, + 3DC53989220F2C940035D3A3 /* libjsiexecutor-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + ED2971642150620600B7C4FE /* JavaScriptCore.framework */, + 2D16E6891FA4F8E400B85C8A /* libReact.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3DC5395B220F2C940035D3A3 /* Products */ = { + isa = PBXGroup; + children = ( + 3DC5398C220F2C940035D3A3 /* libRNCAsyncstorage.a */, + ); + name = Products; + sourceTree = ""; + }; + 5E91572E1DD0AC6500FF2AA8 /* Products */ = { + isa = PBXGroup; + children = ( + 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, + ); + name = Products; + sourceTree = ""; + }; + 78C398B11ACF4ADC00677621 /* Products */ = { + isa = PBXGroup; + children = ( + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, + 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, + 146833FF1AC3E56700842450 /* React.xcodeproj */, + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, + ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */, + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, + ); + name = Libraries; + sourceTree = ""; + }; + 832341B11AAA6A8300B99B32 /* Products */ = { + isa = PBXGroup; + children = ( + 832341B51AAA6A8300B99B32 /* libRCTText.a */, + 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 3DC5395A220F2C940035D3A3 /* RNCAsyncstorage.xcodeproj */, + 13B07FAE1A68108700A75B9A /* AsyncStorageExample */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* AsyncStorageExample.app */, + ); + name = Products; + sourceTree = ""; + }; + ADBDB9201DFEBF0600ED6528 /* Products */ = { + isa = PBXGroup; + children = ( + ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 13B07F861A680F5B00A75B9A /* AsyncStorageExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AsyncStorageExample" */; + buildPhases = ( + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AsyncStorageExample; + productName = "Hello World"; + productReference = 13B07F961A680F5B00A75B9A /* AsyncStorageExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = Facebook; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AsyncStorageExample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; + ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + }, + { + ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */; + ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; + }, + { + ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */; + ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + }, + { + ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; + ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + }, + { + ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; + ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + }, + { + ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; + ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + }, + { + ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; + ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + }, + { + ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; + ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + }, + { + ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; + ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + }, + { + ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; + ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + }, + { + ProductGroup = 139FDEE71B06529A00C62182 /* Products */; + ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + }, + { + ProductGroup = 146834001AC3E56700842450 /* Products */; + ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; + }, + { + ProductGroup = 3DC5395B220F2C940035D3A3 /* Products */; + ProjectRef = 3DC5395A220F2C940035D3A3 /* RNCAsyncstorage.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* AsyncStorageExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTActionSheet.a; + remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTGeolocation.a; + remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImage.a; + remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTNetwork.a; + remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTVibration.a; + remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTSettings.a; + remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTWebSocket.a; + remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 146834041AC3E56700842450 /* libReact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReact.a; + remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTBlob-tvOS.a"; + remoteRef = 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libfishhook.a; + remoteRef = 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libfishhook-tvOS.a"; + remoteRef = 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFDF2056DD460020B375 /* libjsinspector.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsinspector.a; + remoteRef = 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsinspector-tvOS.a"; + remoteRef = 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFE32056DD460020B375 /* libthird-party.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libthird-party.a"; + remoteRef = 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFE52056DD460020B375 /* libthird-party.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libthird-party.a"; + remoteRef = 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libdouble-conversion.a"; + remoteRef = 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libdouble-conversion.a"; + remoteRef = 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTImage-tvOS.a"; + remoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTLinking-tvOS.a"; + remoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTNetwork-tvOS.a"; + remoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTSettings-tvOS.a"; + remoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTText-tvOS.a"; + remoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRCTWebSocket-tvOS.a"; + remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3EA31DF850E9000B6D8A /* libReact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReact.a; + remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libyoga.a; + remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libyoga.a; + remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libcxxreact.a; + remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libcxxreact.a; + remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DC53983220F2C940035D3A3 /* libjsi.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsi.a; + remoteRef = 3DC53982220F2C940035D3A3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DC53985220F2C940035D3A3 /* libjsiexecutor.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libjsiexecutor.a; + remoteRef = 3DC53984220F2C940035D3A3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DC53987220F2C940035D3A3 /* libjsi-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsi-tvOS.a"; + remoteRef = 3DC53986220F2C940035D3A3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DC53989220F2C940035D3A3 /* libjsiexecutor-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libjsiexecutor-tvOS.a"; + remoteRef = 3DC53988220F2C940035D3A3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3DC5398C220F2C940035D3A3 /* libRNCAsyncstorage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNCAsyncstorage.a; + remoteRef = 3DC5398B220F2C940035D3A3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAnimation.a; + remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAnimation.a; + remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTLinking.a; + remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTText.a; + remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTBlob.a; + remoteRef = ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export NODE_BINARY=node\n../../node_modules/react-native/scripts/react-native-xcode.sh"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + path = AsyncStorageExample; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = NO; + INFOPLIST_FILE = AsyncStorageExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = AsyncStorageExample; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = AsyncStorageExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = AsyncStorageExample; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AsyncStorageExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AsyncStorageExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample-tvOS.xcscheme b/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample-tvOS.xcscheme new file mode 100644 index 00000000..d7047ae8 --- /dev/null +++ b/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample-tvOS.xcscheme @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample.xcscheme b/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample.xcscheme new file mode 100644 index 00000000..17666f5f --- /dev/null +++ b/example/ios/AsyncStorageExample.xcodeproj/xcshareddata/xcschemes/AsyncStorageExample.xcscheme @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/AsyncStorageExample/AppDelegate.h b/example/ios/AsyncStorageExample/AppDelegate.h new file mode 100644 index 00000000..4b5644f2 --- /dev/null +++ b/example/ios/AsyncStorageExample/AppDelegate.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/example/ios/AsyncStorageExample/AppDelegate.m b/example/ios/AsyncStorageExample/AppDelegate.m new file mode 100644 index 00000000..18f05547 --- /dev/null +++ b/example/ios/AsyncStorageExample/AppDelegate.m @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "AppDelegate.h" + +#import +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + NSURL *jsCodeLocation; + + jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:nil]; + + RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation + moduleName:@"AsyncStorageExample" + initialProperties:nil + launchOptions:launchOptions]; + rootView.backgroundColor = [UIColor blackColor]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [UIViewController new]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/example/ios/AsyncStorageExample/Base.lproj/LaunchScreen.xib b/example/ios/AsyncStorageExample/Base.lproj/LaunchScreen.xib new file mode 100644 index 00000000..018333da --- /dev/null +++ b/example/ios/AsyncStorageExample/Base.lproj/LaunchScreen.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/AsyncStorageExample/Images.xcassets/AppIcon.appiconset/Contents.json b/example/ios/AsyncStorageExample/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..19882d56 --- /dev/null +++ b/example/ios/AsyncStorageExample/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/example/ios/AsyncStorageExample/Images.xcassets/Contents.json b/example/ios/AsyncStorageExample/Images.xcassets/Contents.json new file mode 100644 index 00000000..2d92bd53 --- /dev/null +++ b/example/ios/AsyncStorageExample/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/example/ios/AsyncStorageExample/Info.plist b/example/ios/AsyncStorageExample/Info.plist new file mode 100644 index 00000000..1c36c0fe --- /dev/null +++ b/example/ios/AsyncStorageExample/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + AsyncStorageExample + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSLocationWhenInUseUsageDescription + + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + + diff --git a/example/ios/AsyncStorageExample/main.m b/example/ios/AsyncStorageExample/main.m new file mode 100644 index 00000000..c316cf81 --- /dev/null +++ b/example/ios/AsyncStorageExample/main.m @@ -0,0 +1,16 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/example/src/App.js b/example/src/App.js new file mode 100644 index 00000000..946958e0 --- /dev/null +++ b/example/src/App.js @@ -0,0 +1,122 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +import React, {Component} from 'react'; +import { + StyleSheet, + SafeAreaView, + Text, + TouchableOpacity, + View, +} from 'react-native'; + +import SimpleGetSet from './examples/GetSet'; +import ClearStorage from './examples/ClearSingle'; + +const EXAMPLES = [ + { + title: 'Simple Get/Set value', + description: 'Store and retrieve persisted data', + render() { + return ; + }, + }, + { + title: 'Clear', + description: 'Clear persisting data storage', + render() { + return ; + }, + }, +]; + +type Props = {}; +type State = {restarting: boolean}; + +export default class App extends Component { + state = { + restarting: false, + }; + + componentDidUpdate() { + if (this.state.restarting) { + this.setState({restarting: false}); + } + } + + _simulateRestart = () => { + this.setState({restarting: true}); + }; + + render() { + const {restarting} = this.state; + return ( + + + Simulate Restart + + {restarting + ? null + : EXAMPLES.map(example => { + return ( + + {example.title} + + {example.description} + + + {example.render(this._simulateRestart)} + + + ); + })} + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#F5FCFF', + padding: 14, + }, + exampleContainer: { + padding: 16, + backgroundColor: '#FFF', + borderColor: '#EEE', + borderTopWidth: 1, + borderBottomWidth: 1, + }, + exampleTitle: { + fontSize: 18, + }, + exampleDescription: { + color: '#333333', + marginBottom: 16, + }, + exampleInnerContainer: { + borderColor: '#EEE', + borderTopWidth: 1, + paddingTop: 16, + }, + restartButton: { + padding: 15, + fontSize: 16, + borderRadius: 5, + backgroundColor: '#F3F3F3', + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'flex-end', + }, +}); diff --git a/example/src/examples/ClearSingle.js b/example/src/examples/ClearSingle.js new file mode 100644 index 00000000..9c13c6e8 --- /dev/null +++ b/example/src/examples/ClearSingle.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +import React, {Component} from 'react'; +import {Text, View, Button} from 'react-native'; + +import AsyncStorage from '@react-native-community/asyns-storage'; + +import {STORAGE_KEY} from './GetSet'; + +type Props = { + resetFunction: () => void, +}; +type State = { + storedNumber: number, + needRestart: boolean, +}; +export default class Clear extends Component { + state = { + needRestart: false, + }; + + cleanItem = async () => { + await AsyncStorage.removeItem(STORAGE_KEY); + + this.setState({needRestart: true}); + }; + + render() { + const {needRestart} = this.state; + return ( + +