From 7666a7fca102e2ff6728fdae0a541278a66f5c27 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 27 Jul 2018 22:31:35 +0800 Subject: [PATCH 01/58] chore: replace npm with yarn --- package-lock.json | 7358 --------------------------------------------- package.json | 24 +- yarn.lock | 5227 ++++++++++++++++++++++++++++++++ 3 files changed, 5239 insertions(+), 7370 deletions(-) delete mode 100644 package-lock.json create mode 100644 yarn.lock diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index af2e838..0000000 --- a/package-lock.json +++ /dev/null @@ -1,7358 +0,0 @@ -{ - "name": "stuhome", - "version": "1.6.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@expo/react-native-action-sheet": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/@expo/react-native-action-sheet/download/@expo/react-native-action-sheet-1.0.1.tgz", - "integrity": "sha1-wC82aIoeT43GCJD/PHNJRK9UHGs=", - "requires": { - "hoist-non-react-statics": "2.3.1", - "prop-types": "15.6.0" - } - }, - "absolute-path": { - "version": "0.0.0", - "resolved": "http://registry.npm.taobao.org/absolute-path/download/absolute-path-0.0.0.tgz", - "integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=" - }, - "accepts": { - "version": "1.2.13", - "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.5.3" - } - }, - "acorn": { - "version": "5.3.0", - "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-5.3.0.tgz", - "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "http://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "ansi": { - "version": "0.3.1", - "resolved": "http://registry.npm.taobao.org/ansi/download/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" - }, - "ansi-escapes": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-3.0.0.tgz", - "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=" - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/ansi-gray/download/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/ansi-wrap/download/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" - }, - "anymatch": { - "version": "1.3.2", - "resolved": "http://registry.npm.taobao.org/anymatch/download/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", - "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } - }, - "apsl-react-native-button": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/apsl-react-native-button/download/apsl-react-native-button-3.1.0.tgz", - "integrity": "sha1-j+br9zTMXxAGxusdVDcKvDw4M/U=", - "requires": { - "lodash.isequal": "4.5.0", - "prop-types": "15.6.0" - } - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "http://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "argparse": { - "version": "1.0.9", - "resolved": "http://registry.npm.taobao.org/argparse/download/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/arr-diff/download/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" - }, - "array-differ": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/array-differ/download/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, - "array-filter": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/array-filter/download/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" - }, - "array-map": { - "version": "0.0.0", - "resolved": "http://registry.npm.taobao.org/array-map/download/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "http://registry.npm.taobao.org/array-reduce/download/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" - }, - "array-union": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/array-unique/download/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" - }, - "arrify": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "art": { - "version": "0.10.1", - "resolved": "http://registry.npm.taobao.org/art/download/art-0.10.1.tgz", - "integrity": "sha1-OFQYg+OZIlxeGT/yRujxV897IUY=" - }, - "asap": { - "version": "2.0.6", - "resolved": "http://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.3", - "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/assertion-error/download/assertion-error-1.1.0.tgz", - "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", - "dev": true - }, - "async": { - "version": "2.6.0", - "resolved": "http://registry.npm.taobao.org/async/download/async-2.6.0.tgz", - "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", - "requires": { - "lodash": "4.17.4" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "babel": { - "version": "6.5.2", - "resolved": "http://registry.npm.taobao.org/babel/download/babel-6.5.2.tgz", - "integrity": "sha1-WRQGB0OCcJIAR/9W8CsthjDC0Sk=", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-core": { - "version": "6.22.1", - "resolved": "http://registry.npm.taobao.org/babel-core/download/babel-core-6.22.1.tgz", - "integrity": "sha1-nF/WWLoXctKNch9tJdlo/HriFkg=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "babel-eslint": { - "version": "6.0.0-beta.6", - "resolved": "http://registry.npm.taobao.org/babel-eslint/download/babel-eslint-6.0.0-beta.6.tgz", - "integrity": "sha1-axpscicRFQWYe1i+XGBsP5yopQM=", - "dev": true, - "requires": { - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash.assign": "3.2.0", - "lodash.pick": "3.1.0" - } - }, - "babel-generator": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-generator/download/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.7", - "trim-right": "1.0.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-builder-binary-assignment-operator-visitor/download/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-helper-builder-react-jsx/download/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "esutils": "2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-call-delegate/download/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-helper-define-map/download/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-explode-assignable-expression/download/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-function-name/download/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-get-function-arity/download/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-hoist-variables/download/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-optimise-call-expression/download/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-helper-regex/download/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-remap-async-to-generator/download/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helper-replace-supers/download/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-helpers/download/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "http://registry.npm.taobao.org/babel-messages/download/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-check-es2015-constants/download/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-external-helpers": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-external-helpers/download/babel-plugin-external-helpers-6.22.0.tgz", - "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-react-transform": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-react-transform/download/babel-plugin-react-transform-3.0.0.tgz", - "integrity": "sha1-QC8lE3t7tm6bVOrXVVffvH7KqnQ=", - "requires": { - "lodash": "4.17.4" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-async-functions/download/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-class-properties/download/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-dynamic-import/download/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-exponentiation-operator/download/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-flow/download/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-jsx/download/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-object-rest-spread/download/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-syntax-trailing-function-commas/download/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.16.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-async-to-generator/download/babel-plugin-transform-async-to-generator-6.16.0.tgz", - "integrity": "sha1-Gew2yxSGtZ+fRorfpCzhOQjKKZk=", - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-class-properties/download/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-arrow-functions/download/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-block-scoped-functions/download/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-block-scoping/download/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-classes/download/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-computed-properties/download/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-destructuring/download/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-for-of/download/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-function-name/download/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-literals/download/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-modules-commonjs/download/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-object-super/download/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-parameters/download/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-shorthand-properties/download/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-spread/download/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-sticky-regex/download/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-template-literals/download/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es2015-unicode-regex/download/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-es3-member-expression-literals": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es3-member-expression-literals/download/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", - "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es3-property-literals": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-es3-property-literals/download/babel-plugin-transform-es3-property-literals-6.22.0.tgz", - "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-exponentiation-operator/download/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-flow-strip-types/download/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-assign": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-object-assign/download/babel-plugin-transform-object-assign-6.22.0.tgz", - "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-object-rest-spread/download/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-react-display-name/download/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-react-jsx/download/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "requires": { - "babel-helper-builder-react-jsx": "6.26.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-react-jsx-source/download/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-regenerator/download/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "requires": { - "regenerator-transform": "0.10.1" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "http://registry.npm.taobao.org/babel-plugin-transform-strict-mode/download/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-preset-es2015-node": { - "version": "6.1.1", - "resolved": "http://registry.npm.taobao.org/babel-preset-es2015-node/download/babel-preset-es2015-node-6.1.1.tgz", - "integrity": "sha1-YLIxVwJLDP6/OmNVTLBe4DW05V8=", - "requires": { - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "semver": "5.4.1" - } - }, - "babel-preset-fbjs": { - "version": "2.1.4", - "resolved": "http://registry.npm.taobao.org/babel-preset-fbjs/download/babel-preset-fbjs-2.1.4.tgz", - "integrity": "sha1-IvNY5mVAc6z2HkegUqd317zPA68=", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es3-member-expression-literals": "6.22.0", - "babel-plugin-transform-es3-property-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1" - } - }, - "babel-preset-react-native": { - "version": "1.9.1", - "resolved": "http://registry.npm.taobao.org/babel-preset-react-native/download/babel-preset-react-native-1.9.1.tgz", - "integrity": "sha1-7I43gnRBDXj1UPqfjt1wNT87sv4=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-react-transform": "2.0.2", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-assign": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-plugin-transform-regenerator": "6.26.0", - "react-transform-hmr": "1.0.4" - }, - "dependencies": { - "babel-plugin-react-transform": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/babel-plugin-react-transform/download/babel-plugin-react-transform-2.0.2.tgz", - "integrity": "sha1-UVu/qZaJOYEULZCx+bFjXeKZUQk=", - "dev": true, - "requires": { - "lodash": "4.17.4" - } - } - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-register/download/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.3", - "home-or-tmp": "2.0.0", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - }, - "dependencies": { - "babel-core": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "core-js": { - "version": "2.5.3", - "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" - }, - "dependencies": { - "core-js": { - "version": "2.5.3", - "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-template/download/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-traverse/download/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-types/download/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.4", - "to-fast-properties": "1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "http://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base64-js": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-1.2.1.tgz", - "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=" - }, - "base64-url": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/base64-url/download/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=" - }, - "basic-auth": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/basic-auth/download/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=" - }, - "basic-auth-connect": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/basic-auth-connect/download/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" - }, - "batch": { - "version": "0.5.3", - "resolved": "http://registry.npm.taobao.org/batch/download/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/beeper/download/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" - }, - "big-integer": { - "version": "1.6.26", - "resolved": "http://registry.npm.taobao.org/big-integer/download/big-integer-1.6.26.tgz", - "integrity": "sha1-OvFnL6Ytry1eyvrPblqg0l4Cwcg=" - }, - "body-parser": { - "version": "1.13.3", - "resolved": "http://registry.npm.taobao.org/body-parser/download/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "requires": { - "bytes": "2.1.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "http-errors": "1.3.1", - "iconv-lite": "0.4.11", - "on-finished": "2.3.0", - "qs": "4.0.0", - "raw-body": "2.1.7", - "type-is": "1.6.15" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "iconv-lite": { - "version": "0.4.11", - "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=" - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "4.3.1", - "resolved": "http://registry.npm.taobao.org/boom/download/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.2.0" - } - }, - "bplist-creator": { - "version": "0.0.7", - "resolved": "http://registry.npm.taobao.org/bplist-creator/download/bplist-creator-0.0.7.tgz", - "integrity": "sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU=", - "requires": { - "stream-buffers": "2.2.0" - } - }, - "bplist-parser": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/bplist-parser/download/bplist-parser-0.1.1.tgz", - "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", - "requires": { - "big-integer": "1.6.26" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "http://registry.npm.taobao.org/braces/download/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "bser": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/bser/download/bser-2.0.0.tgz", - "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "requires": { - "node-int64": "0.4.0" - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/builtin-modules/download/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "bytes": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=" - }, - "caller-path": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/caller-path/download/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/callsites/download/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chai": { - "version": "3.5.0", - "resolved": "http://registry.npm.taobao.org/chai/download/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "1.1.0", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "http://registry.npm.taobao.org/chardet/download/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" - }, - "charenc": { - "version": "0.0.2", - "resolved": "http://registry.npm.taobao.org/charenc/download/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" - }, - "cheerio": { - "version": "0.22.0", - "resolved": "http://registry.npm.taobao.org/cheerio/download/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash.assignin": "4.2.0", - "lodash.bind": "4.2.1", - "lodash.defaults": "4.2.0", - "lodash.filter": "4.6.0", - "lodash.flatten": "4.4.0", - "lodash.foreach": "4.5.0", - "lodash.map": "4.6.0", - "lodash.merge": "4.6.0", - "lodash.pick": "4.4.0", - "lodash.reduce": "4.6.0", - "lodash.reject": "4.6.0", - "lodash.some": "4.6.0" - }, - "dependencies": { - "lodash.pick": { - "version": "4.4.0", - "resolved": "http://registry.npm.taobao.org/lodash.pick/download/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - } - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", - "dev": true - }, - "clamp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", - "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/cli-width/download/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "clone": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/clone/download/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/clone-stats/download/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" - }, - "co": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/co/download/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "color-convert": { - "version": "1.9.1", - "resolved": "http://registry.npm.taobao.org/color-convert/download/color-convert-1.9.1.tgz", - "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-support": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/color-support/download/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=" - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.12.2", - "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.12.2.tgz", - "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=" - }, - "compressible": { - "version": "2.0.12", - "resolved": "http://registry.npm.taobao.org/compressible/download/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", - "requires": { - "mime-db": "1.30.0" - } - }, - "compression": { - "version": "1.5.2", - "resolved": "http://registry.npm.taobao.org/compression/download/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "requires": { - "accepts": "1.2.13", - "bytes": "2.1.0", - "compressible": "2.0.12", - "debug": "2.2.0", - "on-headers": "1.0.1", - "vary": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "connect": { - "version": "2.30.2", - "resolved": "http://registry.npm.taobao.org/connect/download/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", - "requires": { - "basic-auth-connect": "1.0.0", - "body-parser": "1.13.3", - "bytes": "2.1.0", - "compression": "1.5.2", - "connect-timeout": "1.6.2", - "content-type": "1.0.4", - "cookie": "0.1.3", - "cookie-parser": "1.3.5", - "cookie-signature": "1.0.6", - "csurf": "1.8.3", - "debug": "2.2.0", - "depd": "1.0.1", - "errorhandler": "1.4.3", - "express-session": "1.11.3", - "finalhandler": "0.4.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "method-override": "2.3.10", - "morgan": "1.6.1", - "multiparty": "3.3.2", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "pause": "0.1.0", - "qs": "4.0.0", - "response-time": "2.3.2", - "serve-favicon": "2.3.2", - "serve-index": "1.7.3", - "serve-static": "1.10.3", - "type-is": "1.6.15", - "utils-merge": "1.0.0", - "vhost": "3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "connect-timeout": { - "version": "1.6.2", - "resolved": "http://registry.npm.taobao.org/connect-timeout/download/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "requires": { - "debug": "2.2.0", - "http-errors": "1.3.1", - "ms": "0.7.1", - "on-headers": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "http://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" - }, - "cookie": { - "version": "0.1.3", - "resolved": "http://registry.npm.taobao.org/cookie/download/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=" - }, - "cookie-parser": { - "version": "1.3.5", - "resolved": "http://registry.npm.taobao.org/cookie-parser/download/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "http://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-paste": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/copy-paste/download/copy-paste-1.3.0.tgz", - "integrity": "sha1-p+bEocKP3t8rCB5yuX3y75X0ce0=", - "requires": { - "iconv-lite": "0.4.19", - "sync-exec": "0.6.2" - } - }, - "core-js": { - "version": "1.2.7", - "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "crc": { - "version": "3.3.0", - "resolved": "http://registry.npm.taobao.org/crc/download/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=" - }, - "create-react-class": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/create-react-class/download/create-react-class-15.6.2.tgz", - "integrity": "sha1-zx7RXxKq1/FO9fLf4F5sQvke8Co=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "http://registry.npm.taobao.org/crypt/download/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "http://registry.npm.taobao.org/boom/download/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "csrf": { - "version": "3.0.6", - "resolved": "http://registry.npm.taobao.org/csrf/download/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.5", - "uid-safe": "2.1.4" - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/css-what/download/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "csurf": { - "version": "1.8.3", - "resolved": "http://registry.npm.taobao.org/csurf/download/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "csrf": "3.0.6", - "http-errors": "1.3.1" - } - }, - "cubic-bezier": { - "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/cubic-bezier/download/cubic-bezier-0.1.2.tgz", - "integrity": "sha1-1JcJQgAuRTcuCqkttlfjnq9oJNc=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/d/download/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.37" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/dateformat/download/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" - }, - "debug": { - "version": "2.6.9", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "http://registry.npm.taobao.org/deep-eql/download/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/type-detect/download/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "http://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/define-properties/download/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, - "del": { - "version": "2.2.2", - "resolved": "http://registry.npm.taobao.org/del/download/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "denodeify": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/denodeify/download/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=" - }, - "depd": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/detect-indent/download/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "2.0.1" - } - }, - "diff": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/diff/download/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "doctrine": { - "version": "1.5.0", - "resolved": "http://registry.npm.taobao.org/doctrine/download/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/dom-walk/download/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.1", - "resolved": "http://registry.npm.taobao.org/domhandler/download/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "http://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "http://registry.npm.taobao.org/duplexer2/download/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "requires": { - "readable-stream": "1.1.14" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encoding": { - "version": "0.1.12", - "resolved": "http://registry.npm.taobao.org/encoding/download/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "0.4.19" - } - }, - "entities": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/entities/download/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "envinfo": { - "version": "3.10.0", - "resolved": "http://registry.npm.taobao.org/envinfo/download/envinfo-3.10.0.tgz", - "integrity": "sha1-JLUqXBmvN53DJGXRkJ43NE3EHCA=", - "requires": { - "copy-paste": "1.3.0", - "glob": "7.1.2", - "minimist": "1.2.0", - "os-name": "2.0.1", - "which": "1.3.0" - } - }, - "enzyme": { - "version": "2.7.0", - "resolved": "http://registry.npm.taobao.org/enzyme/download/enzyme-2.7.0.tgz", - "integrity": "sha1-dyR3gAVHyiUUzAryWOZHwWau6Jk=", - "dev": true, - "requires": { - "cheerio": "0.22.0", - "function.prototype.name": "1.1.0", - "is-subset": "0.1.1", - "lodash": "4.17.4", - "object-is": "1.0.1", - "object.assign": "4.1.0", - "object.entries": "1.0.4", - "object.values": "1.0.4", - "uuid": "2.0.3" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } - } - }, - "errno": { - "version": "0.1.6", - "resolved": "http://registry.npm.taobao.org/errno/download/errno-0.1.6.tgz", - "integrity": "sha1-w4bOimKD8U/AlWO3FWCQjJv1MCY=", - "requires": { - "prr": "1.0.1" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/error-ex/download/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "requires": { - "is-arrayish": "0.2.1" - } - }, - "errorhandler": { - "version": "1.4.3", - "resolved": "http://registry.npm.taobao.org/errorhandler/download/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", - "requires": { - "accepts": "1.3.4", - "escape-html": "1.0.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - } - } - }, - "es-abstract": { - "version": "1.10.0", - "resolved": "http://registry.npm.taobao.org/es-abstract/download/es-abstract-1.10.0.tgz", - "integrity": "sha1-Hss2wZeEKgDY7kwt/YZGu5fWCGQ=", - "dev": true, - "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.1", - "has": "1.0.1", - "is-callable": "1.1.3", - "is-regex": "1.0.4" - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" - } - }, - "es5-ext": { - "version": "0.10.37", - "resolved": "http://registry.npm.taobao.org/es5-ext/download/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/es6-iterator/download/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "http://registry.npm.taobao.org/es6-map/download/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "http://registry.npm.taobao.org/es6-set/download/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "http://registry.npm.taobao.org/es6-symbol/download/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/es6-weak-map/download/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escope": { - "version": "3.6.0", - "resolved": "http://registry.npm.taobao.org/escope/download/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, - "eslint": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/eslint/download/eslint-2.4.0.tgz", - "integrity": "sha1-v7OO/Lf5mBiApyS8LmHSFAku46k=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "1.5.0", - "es6-map": "0.1.5", - "escope": "3.6.0", - "espree": "3.5.2", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "1.3.1", - "glob": "6.0.4", - "globals": "8.18.0", - "ignore": "2.2.19", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.1", - "is-resolvable": "1.0.1", - "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", - "lodash": "4.17.4", - "mkdirp": "0.5.1", - "optionator": "0.8.2", - "path-is-absolute": "1.0.1", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "resolve": "1.5.0", - "shelljs": "0.5.3", - "strip-json-comments": "1.0.4", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/cli-cursor/download/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "1.0.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "http://registry.npm.taobao.org/figures/download/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "glob": { - "version": "6.0.4", - "resolved": "http://registry.npm.taobao.org/glob/download/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "globals": { - "version": "8.18.0", - "resolved": "http://registry.npm.taobao.org/globals/download/globals-8.18.0.tgz", - "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", - "dev": true - }, - "inquirer": { - "version": "0.12.0", - "resolved": "http://registry.npm.taobao.org/inquirer/download/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/onetime/download/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/restore-cursor/download/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/run-async/download/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "http://registry.npm.taobao.org/rx-lite/download/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "eslint-plugin-react": { - "version": "4.2.3", - "resolved": "http://registry.npm.taobao.org/eslint-plugin-react/download/eslint-plugin-react-4.2.3.tgz", - "integrity": "sha1-eaoCBbnP6MmPh0ewTH7n0EO+g98=", - "dev": true - }, - "espree": { - "version": "3.5.2", - "resolved": "http://registry.npm.taobao.org/espree/download/espree-3.5.2.tgz", - "integrity": "sha1-dWrai5eenc/NswqtjRqTBKkF4co=", - "dev": true, - "requires": { - "acorn": "5.3.0", - "acorn-jsx": "3.0.1" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", - "dev": true - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/esrecurse/download/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/estraverse/download/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/esutils/download/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.7.0", - "resolved": "http://registry.npm.taobao.org/etag/download/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "http://registry.npm.taobao.org/event-emitter/download/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37" - } - }, - "event-target-shim": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/event-target-shim/download/event-target-shim-1.1.1.tgz", - "integrity": "sha1-qG5e5r2qFgVEddp5fM3fDFVphJE=" - }, - "exec-sh": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/exec-sh/download/exec-sh-0.2.1.tgz", - "integrity": "sha1-FjuYpuiea2W0fCoo0hW8H2OYnDg=", - "requires": { - "merge": "1.2.0" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/execa/download/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/exit-hook/download/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "http://registry.npm.taobao.org/expand-brackets/download/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "http://registry.npm.taobao.org/expand-range/download/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "2.2.3" - } - }, - "express-session": { - "version": "1.11.3", - "resolved": "http://registry.npm.taobao.org/express-session/download/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", - "requires": { - "cookie": "0.1.3", - "cookie-signature": "1.0.6", - "crc": "3.3.0", - "debug": "2.2.0", - "depd": "1.0.1", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "uid-safe": "2.0.0", - "utils-merge": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - }, - "uid-safe": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/uid-safe/download/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "requires": { - "base64-url": "1.2.1" - } - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/extend/download/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "external-editor": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/external-editor/download/external-editor-2.1.0.tgz", - "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", - "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "http://registry.npm.taobao.org/extglob/download/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "http://registry.npm.taobao.org/fancy-log/download/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "http://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fb-watchman": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/fb-watchman/download/fb-watchman-2.0.0.tgz", - "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "requires": { - "bser": "2.0.0" - } - }, - "fbjs": { - "version": "0.8.16", - "resolved": "http://registry.npm.taobao.org/fbjs/download/fbjs-0.8.16.tgz", - "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", - "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.17" - } - }, - "fbjs-scripts": { - "version": "0.8.1", - "resolved": "http://registry.npm.taobao.org/fbjs-scripts/download/fbjs-scripts-0.8.1.tgz", - "integrity": "sha1-wcbvvst/AIR4Rol2t4OIDC9ml2U=", - "requires": { - "babel-core": "6.26.0", - "babel-preset-fbjs": "2.1.4", - "core-js": "2.5.3", - "cross-spawn": "5.1.0", - "gulp-util": "3.0.8", - "object-assign": "4.1.1", - "semver": "5.4.1", - "through2": "2.0.3" - }, - "dependencies": { - "babel-core": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "core-js": { - "version": "2.5.3", - "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - } - } - }, - "figures": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/figures/download/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-entry-cache": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-1.3.1.tgz", - "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", - "dev": true, - "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/filename-regex/download/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" - }, - "fill-range": { - "version": "2.2.3", - "resolved": "http://registry.npm.taobao.org/fill-range/download/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "finalhandler": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/finalhandler/download/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "requires": { - "debug": "2.2.0", - "escape-html": "1.0.2", - "on-finished": "2.3.0", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "escape-html": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=" - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "2.0.0" - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/flat-cache/download/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "0.1.5", - "resolved": "http://registry.npm.taobao.org/for-own/download/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "requires": { - "for-in": "1.0.2" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "http://registry.npm.taobao.org/foreach/download/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.1", - "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "fresh": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/fresh/download/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/fsevents/download/fsevents-1.1.3.tgz", - "integrity": "sha1-EfgjGPX+e7LNIpZaEI6TBiCCFtg=", - "optional": true, - "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.39", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/function.prototype.name/download/function.prototype.name-1.1.0.tgz", - "integrity": "sha1-i9djzAr4YKhZzF1JOE10uTLNIyc=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "is-callable": "1.1.3" - } - }, - "gauge": { - "version": "1.2.7", - "resolved": "http://registry.npm.taobao.org/gauge/download/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "requires": { - "ansi": "0.3.1", - "has-unicode": "2.0.1", - "lodash.pad": "4.5.1", - "lodash.padend": "4.6.1", - "lodash.padstart": "4.6.1" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/generate-function/download/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/generate-object-property/download/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "http://registry.npm.taobao.org/glob/download/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/glob-base/download/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/glob-parent/download/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "2.0.1" - } - }, - "global": { - "version": "4.3.2", - "resolved": "http://registry.npm.taobao.org/global/download/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "2.19.0", - "process": "0.5.2" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "http://registry.npm.taobao.org/globals/download/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=" - }, - "globby": { - "version": "5.0.0", - "resolved": "http://registry.npm.taobao.org/globby/download/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/glogg/download/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/graceful-readlink/download/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "http://registry.npm.taobao.org/growl/download/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "growly": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/growly/download/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "http://registry.npm.taobao.org/gulp-util/download/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/gulplog/download/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "requires": { - "glogg": "1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.0.3", - "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "has": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/has/download/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, - "requires": { - "function-bind": "1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/has-gulplog/download/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "requires": { - "sparkles": "1.0.0" - } - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hawk": { - "version": "6.0.2", - "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=" - }, - "hoist-non-react-statics": { - "version": "2.3.1", - "resolved": "http://registry.npm.taobao.org/hoist-non-react-statics/download/hoist-non-react-statics-2.3.1.tgz", - "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=" - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/home-or-tmp/download/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "http://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=" - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "http://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "http-errors": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/http-errors/download/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "requires": { - "inherits": "2.0.3", - "statuses": "1.4.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" - }, - "ignore": { - "version": "2.2.19", - "resolved": "http://registry.npm.taobao.org/ignore/download/ignore-2.2.19.tgz", - "integrity": "sha1-TIRaYfflC0pBD2FWqqOLatleDI8=", - "dev": true - }, - "image-size": { - "version": "0.6.2", - "resolved": "http://registry.npm.taobao.org/image-size/download/image-size-0.6.2.tgz", - "integrity": "sha1-juMW1CmLAouWUJG2c9XxU3re5bQ=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "http://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "inquirer": { - "version": "3.3.0", - "resolved": "http://registry.npm.taobao.org/inquirer/download/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.4", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-2.3.0.tgz", - "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "invariant": { - "version": "2.2.2", - "resolved": "http://registry.npm.taobao.org/invariant/download/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "requires": { - "loose-envify": "1.3.1" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/invert-kv/download/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-builtin-module/download/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-callable": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/is-callable/download/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/is-dotfile/download/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "http://registry.npm.taobao.org/is-equal-shallow/download/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-extglob/download/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-finite": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/is-finite/download/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/is-glob/download/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-my-json-valid": { - "version": "2.17.1", - "resolved": "http://registry.npm.taobao.org/is-my-json-valid/download/is-my-json-valid-2.17.1.tgz", - "integrity": "sha1-PamJFKcKIvCoVj7xURokbG/FVHE=", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/is-number/download/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-path-in-cwd/download/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.1" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/is-path-inside/download/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/is-posix-bracket/download/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/is-primitive/download/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/is-property/download/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "1.0.1" - } - }, - "is-resolvable": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.0.1.tgz", - "integrity": "sha1-rMoc022+RLl0uSQyFVWnC6A7HPQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-subset": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/is-subset/download/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, - "is-symbol": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - } - } - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/isomorphic-fetch/download/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "1.7.3", - "whatwg-fetch": "2.0.3" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jest-docblock": { - "version": "21.2.0", - "resolved": "http://registry.npm.taobao.org/jest-docblock/download/jest-docblock-21.2.0.tgz", - "integrity": "sha1-UVKcOzDV/RWdpgwnzu3Blfr41BQ=" - }, - "jest-haste-map": { - "version": "21.2.0", - "resolved": "http://registry.npm.taobao.org/jest-haste-map/download/jest-haste-map-21.2.0.tgz", - "integrity": "sha1-E2PwqLtDOPJPABgGVx7/eksv89g=", - "requires": { - "fb-watchman": "2.0.0", - "graceful-fs": "4.1.11", - "jest-docblock": "21.2.0", - "micromatch": "2.3.11", - "sane": "2.2.0", - "worker-farm": "1.5.2" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "http://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.10.0", - "resolved": "http://registry.npm.taobao.org/js-yaml/download/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/json-stable-stringify/download/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.2", - "resolved": "http://registry.npm.taobao.org/json3/download/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "http://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "http://registry.npm.taobao.org/jsonpointer/download/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "keymirror": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/keymirror/download/keymirror-0.1.1.tgz", - "integrity": "sha1-kYiJ6hP40KQufFVyUO7nE63JXDU=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/klaw/download/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "requires": { - "graceful-fs": "4.1.11" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "1.0.0" - } - }, - "left-pad": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/left-pad/download/left-pad-1.2.0.tgz", - "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=" - }, - "levn": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - }, - "lodash-es": { - "version": "4.17.4", - "resolved": "http://registry.npm.taobao.org/lodash-es/download/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/lodash._baseassign/download/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/lodash._basecopy/download/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "http://registry.npm.taobao.org/lodash._basecreate/download/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._baseflatten": { - "version": "3.1.4", - "resolved": "http://registry.npm.taobao.org/lodash._baseflatten/download/lodash._baseflatten-3.1.4.tgz", - "integrity": "sha1-B3D/gBMa9uNPO1EXlqe6UhTmX/c=", - "dev": true, - "requires": { - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "http://registry.npm.taobao.org/lodash._basefor/download/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/lodash._basetostring/download/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/lodash._basevalues/download/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/lodash._bindcallback/download/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._createassigner": { - "version": "3.1.1", - "resolved": "http://registry.npm.taobao.org/lodash._createassigner/download/lodash._createassigner-3.1.1.tgz", - "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", - "dev": true, - "requires": { - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9", - "lodash.restparam": "3.6.1" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "http://registry.npm.taobao.org/lodash._getnative/download/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "http://registry.npm.taobao.org/lodash._isiterateecall/download/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" - }, - "lodash._pickbyarray": { - "version": "3.0.2", - "resolved": "http://registry.npm.taobao.org/lodash._pickbyarray/download/lodash._pickbyarray-3.0.2.tgz", - "integrity": "sha1-H4mNlgfrVgsOFnOEt3x8bRCKpMU=", - "dev": true - }, - "lodash._pickbycallback": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/lodash._pickbycallback/download/lodash._pickbycallback-3.0.0.tgz", - "integrity": "sha1-/2G5oBens699MObFPeKK+hm4dQo=", - "dev": true, - "requires": { - "lodash._basefor": "3.0.3", - "lodash.keysin": "3.0.8" - } - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/lodash._reescape/download/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/lodash._reevaluate/download/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/lodash._root/download/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" - }, - "lodash.assign": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/lodash.assign/download/lodash.assign-3.2.0.tgz", - "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._createassigner": "3.1.1", - "lodash.keys": "3.1.2" - } - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/lodash.assignin/download/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "http://registry.npm.taobao.org/lodash.bind/download/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "http://registry.npm.taobao.org/lodash.create/download/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/lodash.defaults/download/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/lodash.escape/download/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.filter/download/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "http://registry.npm.taobao.org/lodash.flatten/download/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "http://registry.npm.taobao.org/lodash.foreach/download/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/lodash.isarguments/download/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "http://registry.npm.taobao.org/lodash.isarray/download/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "http://registry.npm.taobao.org/lodash.isequal/download/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "http://registry.npm.taobao.org/lodash.keys/download/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.keysin": { - "version": "3.0.8", - "resolved": "http://registry.npm.taobao.org/lodash.keysin/download/lodash.keysin-3.0.8.tgz", - "integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=", - "dev": true, - "requires": { - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.map/download/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.merge/download/lodash.merge-4.6.0.tgz", - "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=", - "dev": true - }, - "lodash.pad": { - "version": "4.5.1", - "resolved": "http://registry.npm.taobao.org/lodash.pad/download/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=" - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "http://registry.npm.taobao.org/lodash.padend/download/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" - }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "http://registry.npm.taobao.org/lodash.padstart/download/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" - }, - "lodash.pick": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/lodash.pick/download/lodash.pick-3.1.0.tgz", - "integrity": "sha1-8lKoVbIEa2G805BLJvdr0u/GVVA=", - "dev": true, - "requires": { - "lodash._baseflatten": "3.1.4", - "lodash._bindcallback": "3.0.1", - "lodash._pickbyarray": "3.0.2", - "lodash._pickbycallback": "3.0.0", - "lodash.restparam": "3.6.1" - } - }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.reduce/download/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", - "dev": true - }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.reject/download/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "http://registry.npm.taobao.org/lodash.restparam/download/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "http://registry.npm.taobao.org/lodash.some/download/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "http://registry.npm.taobao.org/lodash.template/download/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "http://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/loose-envify/download/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "requires": { - "js-tokens": "3.0.2" - } - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "macos-release": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/macos-release/download/macos-release-1.1.0.tgz", - "integrity": "sha1-gxlF4pNltHCqhySwqzbI+JWdEPs=" - }, - "makeerror": { - "version": "1.0.11", - "resolved": "http://registry.npm.taobao.org/makeerror/download/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "requires": { - "tmpl": "1.0.4" - } - }, - "md5": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/md5/download/md5-2.1.0.tgz", - "integrity": "sha1-IuyS8zrJem703BbA9X+kbAHtE7s=", - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/mem/download/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "merge": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/merge/download/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/merge-stream/download/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "requires": { - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "method-override": { - "version": "2.3.10", - "resolved": "http://registry.npm.taobao.org/method-override/download/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", - "requires": { - "debug": "2.6.9", - "methods": "1.1.2", - "parseurl": "1.3.2", - "vary": "1.1.2" - }, - "dependencies": { - "vary": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "metro-bundler": { - "version": "0.20.3", - "resolved": "http://registry.npm.taobao.org/metro-bundler/download/metro-bundler-0.20.3.tgz", - "integrity": "sha1-De0Btk6JYxFwF7EG91uDz8NPNlY=", - "requires": { - "absolute-path": "0.0.0", - "async": "2.6.0", - "babel-core": "6.26.0", - "babel-generator": "6.26.0", - "babel-plugin-external-helpers": "6.22.0", - "babel-preset-es2015-node": "6.1.1", - "babel-preset-fbjs": "2.1.4", - "babel-preset-react-native": "4.0.0", - "babel-register": "6.26.0", - "babylon": "6.18.0", - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "core-js": "2.5.3", - "debug": "2.6.9", - "denodeify": "1.2.1", - "fbjs": "0.8.16", - "graceful-fs": "4.1.11", - "image-size": "0.6.2", - "jest-docblock": "21.2.0", - "jest-haste-map": "21.2.0", - "json-stable-stringify": "1.0.1", - "json5": "0.4.0", - "left-pad": "1.2.0", - "lodash": "4.17.4", - "merge-stream": "1.0.1", - "mime-types": "2.1.11", - "mkdirp": "0.5.1", - "request": "2.83.0", - "rimraf": "2.6.2", - "source-map": "0.5.7", - "temp": "0.8.3", - "throat": "4.1.0", - "uglify-es": "3.3.5", - "wordwrap": "1.0.0", - "write-file-atomic": "1.3.4", - "xpipe": "1.0.5" - }, - "dependencies": { - "babel-core": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - }, - "dependencies": { - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - } - } - }, - "babel-preset-react-native": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/babel-preset-react-native/download/babel-preset-react-native-4.0.0.tgz", - "integrity": "sha1-PfgN0zpFOIjN0zvbhyJNF6XXOVk=", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-react-transform": "3.0.0", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-assign": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-plugin-transform-regenerator": "6.26.0", - "babel-template": "6.26.0", - "react-transform-hmr": "1.0.4" - } - }, - "core-js": { - "version": "2.5.3", - "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" - }, - "json5": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/json5/download/json5-0.4.0.tgz", - "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=" - }, - "mime-db": { - "version": "1.23.0", - "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.23.0.tgz", - "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=" - }, - "mime-types": { - "version": "2.1.11", - "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.11.tgz", - "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", - "requires": { - "mime-db": "1.23.0" - } - } - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "http://registry.npm.taobao.org/micromatch/download/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz", - "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=" - }, - "mime-db": { - "version": "1.30.0", - "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" - }, - "mime-types": { - "version": "2.1.17", - "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "requires": { - "mime-db": "1.30.0" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" - }, - "min-document": { - "version": "2.19.0", - "resolved": "http://registry.npm.taobao.org/min-document/download/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "0.1.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, - "mocha": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/mocha/download/mocha-3.2.0.tgz", - "integrity": "sha1-fcT0XlCIB1FxpoiWgU5q6et6heM=", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.5", - "glob": "7.0.5", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "glob": { - "version": "7.0.5", - "resolved": "http://registry.npm.taobao.org/glob/download/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "moment": { - "version": "2.19.3", - "resolved": "http://registry.npm.taobao.org/moment/download/moment-2.19.3.tgz", - "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=" - }, - "morgan": { - "version": "1.6.1", - "resolved": "http://registry.npm.taobao.org/morgan/download/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", - "requires": { - "basic-auth": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "on-finished": "2.3.0", - "on-headers": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multiparty": { - "version": "3.3.2", - "resolved": "http://registry.npm.taobao.org/multiparty/download/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "requires": { - "readable-stream": "1.1.14", - "stream-counter": "0.2.0" - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/multipipe/download/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "http://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nan": { - "version": "2.8.0", - "resolved": "http://registry.npm.taobao.org/nan/download/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", - "optional": true - }, - "negotiator": { - "version": "0.5.3", - "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=" - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "http://registry.npm.taobao.org/node-fetch/download/node-fetch-1.7.3.tgz", - "integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=", - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/node-int64/download/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" - }, - "node-notifier": { - "version": "5.1.2", - "resolved": "http://registry.npm.taobao.org/node-notifier/download/node-notifier-5.1.2.tgz", - "integrity": "sha1-L6nhJgX6EACdRFSdb82KY93g5P8=", - "requires": { - "growly": "1.3.0", - "semver": "5.4.1", - "shellwords": "0.1.1", - "which": "1.3.0" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", - "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "2.0.4", - "resolved": "http://registry.npm.taobao.org/npmlog/download/npmlog-2.0.4.tgz", - "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", - "requires": { - "ansi": "0.3.1", - "are-we-there-yet": "1.1.4", - "gauge": "1.2.7" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/nth-check/download/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-is": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/object-is/download/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, - "object-keys": { - "version": "1.0.11", - "resolved": "http://registry.npm.taobao.org/object-keys/download/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "http://registry.npm.taobao.org/object.assign/download/object.assign-4.1.0.tgz", - "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" - } - }, - "object.entries": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/object.entries/download/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.10.0", - "function-bind": "1.1.1", - "has": "1.0.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/object.omit/download/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/object.values/download/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.10.0", - "function-bind": "1.1.1", - "has": "1.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" - }, - "once": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "opn": { - "version": "3.0.3", - "resolved": "http://registry.npm.taobao.org/opn/download/opn-3.0.3.tgz", - "integrity": "sha1-ttmec5n3jWXDuq/+8fsojpuFJDo=", - "requires": { - "object-assign": "4.1.1" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "options": { - "version": "0.0.6", - "resolved": "http://registry.npm.taobao.org/options/download/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz", - "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "os-name": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-2.0.1.tgz", - "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", - "requires": { - "macos-release": "1.1.0", - "win-release": "1.1.1" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.2.0.tgz", - "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "1.2.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "http://registry.npm.taobao.org/parse-glob/download/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/path-is-inside/download/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "requires": { - "pify": "2.3.0" - } - }, - "pause": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/pause/download/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=" - }, - "pegjs": { - "version": "0.10.0", - "resolved": "http://registry.npm.taobao.org/pegjs/download/pegjs-0.10.0.tgz", - "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "plist": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/plist/download/plist-1.2.0.tgz", - "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=", - "requires": { - "base64-js": "0.0.8", - "util-deprecate": "1.0.2", - "xmlbuilder": "4.0.0", - "xmldom": "0.1.27" - }, - "dependencies": { - "base64-js": { - "version": "0.0.8", - "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" - } - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/pluralize/download/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/preserve/download/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" - }, - "pretty-format": { - "version": "4.3.1", - "resolved": "http://registry.npm.taobao.org/pretty-format/download/pretty-format-4.3.1.tgz", - "integrity": "sha1-UwvlxCs8BbNkFKeipDN6qArNDo0=" - }, - "private": { - "version": "0.1.8", - "resolved": "http://registry.npm.taobao.org/private/download/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" - }, - "process": { - "version": "0.5.2", - "resolved": "http://registry.npm.taobao.org/process/download/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "progress": { - "version": "1.1.8", - "resolved": "http://registry.npm.taobao.org/progress/download/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "promise": { - "version": "7.3.1", - "resolved": "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", - "requires": { - "asap": "2.0.6" - } - }, - "prop-types": { - "version": "15.6.0", - "resolved": "http://registry.npm.taobao.org/prop-types/download/prop-types-15.6.0.tgz", - "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "punycode": { - "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=" - }, - "raf": { - "version": "3.4.0", - "resolved": "http://registry.npm.taobao.org/raf/download/raf-3.4.0.tgz", - "integrity": "sha1-ooh2iBtLwsqRF9QTgWPduA94FXU=", - "dev": true, - "requires": { - "performance-now": "2.1.0" - } - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/random-bytes/download/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "randomatic": { - "version": "1.1.7", - "resolved": "http://registry.npm.taobao.org/randomatic/download/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "range-parser": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/range-parser/download/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=" - }, - "raw-body": { - "version": "2.1.7", - "resolved": "http://registry.npm.taobao.org/raw-body/download/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", - "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.13", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" - }, - "iconv-lite": { - "version": "0.4.13", - "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" - } - } - }, - "react": { - "version": "16.0.0", - "resolved": "http://registry.npm.taobao.org/react/download/react-16.0.0.tgz", - "integrity": "sha1-zn348ZQbA28Cssyp29DLHw6FXi0=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "prop-types": "15.6.0" - } - }, - "react-addons-create-fragment": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/react-addons-create-fragment/download/react-addons-create-fragment-15.6.2.tgz", - "integrity": "sha1-o5TefCx77Na1R1uhuXrEcs58dPg=", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "react-addons-perf": { - "version": "15.4.2", - "resolved": "http://registry.npm.taobao.org/react-addons-perf/download/react-addons-perf-15.4.2.tgz", - "integrity": "sha1-EQvc9cRZxPd8uF7WNLzTOXU2ODs=", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "object-assign": "4.1.1" - } - }, - "react-addons-pure-render-mixin": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/react-addons-pure-render-mixin/download/react-addons-pure-render-mixin-15.6.2.tgz", - "integrity": "sha1-a4P0C2s27kBzXL1hJes/E84c3ck=", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "object-assign": "4.1.1" - } - }, - "react-addons-test-utils": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/react-addons-test-utils/download/react-addons-test-utils-15.6.2.tgz", - "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=", - "dev": true - }, - "react-addons-update": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/react-addons-update/download/react-addons-update-15.6.2.tgz", - "integrity": "sha1-5TdTxbNIh5dFEMiC1/sHWFHV5QQ=", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "object-assign": "4.1.1" - } - }, - "react-clone-referenced-element": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/react-clone-referenced-element/download/react-clone-referenced-element-1.0.1.tgz", - "integrity": "sha1-K7qMaUBMXkqUQ5hgC8xMlB+GBoI=" - }, - "react-deep-force-update": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/react-deep-force-update/download/react-deep-force-update-1.1.1.tgz", - "integrity": "sha1-vNMUeAJ7ZLMznxCJIatSC0MT3Cw=" - }, - "react-devtools-core": { - "version": "2.5.2", - "resolved": "http://registry.npm.taobao.org/react-devtools-core/download/react-devtools-core-2.5.2.tgz", - "integrity": "sha1-+XvsWvrl2TGNFneAZeDCFMTVcUw=", - "requires": { - "shell-quote": "1.6.1", - "ws": "2.3.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.0.1", - "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" - }, - "ws": { - "version": "2.3.1", - "resolved": "http://registry.npm.taobao.org/ws/download/ws-2.3.1.tgz", - "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=", - "requires": { - "safe-buffer": "5.0.1", - "ultron": "1.1.1" - } - } - } - }, - "react-dom": { - "version": "15.6.2", - "resolved": "http://registry.npm.taobao.org/react-dom/download/react-dom-15.6.2.tgz", - "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=", - "dev": true, - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "prop-types": "15.6.0" - } - }, - "react-native": { - "version": "0.51.0", - "resolved": "http://registry.npm.taobao.org/react-native/download/react-native-0.51.0.tgz", - "integrity": "sha1-/iWTSzAw/TI/PKGnDwNBM0ZZVe0=", - "requires": { - "absolute-path": "0.0.0", - "art": "0.10.1", - "babel-core": "6.26.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.16.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "base64-js": "1.2.1", - "chalk": "1.1.3", - "commander": "2.12.2", - "connect": "2.30.2", - "create-react-class": "15.6.2", - "debug": "2.6.9", - "denodeify": "1.2.1", - "envinfo": "3.10.0", - "event-target-shim": "1.1.1", - "fbjs": "0.8.16", - "fbjs-scripts": "0.8.1", - "fs-extra": "1.0.0", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "inquirer": "3.3.0", - "lodash": "4.17.4", - "metro-bundler": "0.20.3", - "mime": "1.6.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "node-fetch": "1.7.3", - "node-notifier": "5.1.2", - "npmlog": "2.0.4", - "opn": "3.0.3", - "optimist": "0.6.1", - "plist": "1.2.0", - "pretty-format": "4.3.1", - "promise": "7.3.1", - "prop-types": "15.6.0", - "react-clone-referenced-element": "1.0.1", - "react-devtools-core": "2.5.2", - "react-timer-mixin": "0.13.3", - "regenerator-runtime": "0.11.1", - "rimraf": "2.6.2", - "semver": "5.4.1", - "shell-quote": "1.6.1", - "stacktrace-parser": "0.1.4", - "whatwg-fetch": "1.1.1", - "ws": "1.1.5", - "xcode": "0.9.3", - "xmldoc": "0.4.0", - "yargs": "9.0.1" - }, - "dependencies": { - "babel-core": { - "version": "6.26.0", - "resolved": "http://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - } - }, - "whatwg-fetch": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/whatwg-fetch/download/whatwg-fetch-1.1.1.tgz", - "integrity": "sha1-rDydOfMgxtzlM5lp0FTvQ90zMxk=" - } - } - }, - "react-native-checkbox": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/react-native-checkbox/download/react-native-checkbox-2.0.0.tgz", - "integrity": "sha1-RTu/0uBVoh5p6+eEJBSgVdUP9Ek=", - "requires": { - "prop-types": "15.6.0" - } - }, - "react-native-communications": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/react-native-communications/download/react-native-communications-2.2.1.tgz", - "integrity": "sha1-eIO1ayCgAu63kMET+GFuqGksp5U=" - }, - "react-native-dismiss-keyboard": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz", - "integrity": "sha1-MohiQrPyMX4SHzrrmwpYXiuHm0k=" - }, - "react-native-drawer-layout": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz", - "integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==", - "requires": { - "react-native-dismiss-keyboard": "1.0.0" - } - }, - "react-native-drawer-layout-polyfill": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/react-native-drawer-layout-polyfill/-/react-native-drawer-layout-polyfill-1.3.2.tgz", - "integrity": "sha512-XzPhfLDJrYHru+e8+dFwhf0FtTeAp7JXPpFYezYV6P1nTeA1Tia/kDpFT+O2DWTrBKBEI8FGhZnThrroZmHIxg==", - "requires": { - "react-native-drawer-layout": "1.3.2" - } - }, - "react-native-gifted-chat": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/react-native-gifted-chat/download/react-native-gifted-chat-0.3.0.tgz", - "integrity": "sha1-qzcXI+PdrQc4XQ/x2/yuFWFR2q0=", - "requires": { - "@expo/react-native-action-sheet": "1.0.1", - "md5": "2.2.1", - "moment": "2.19.3", - "prop-types": "15.5.10", - "react-native-communications": "2.2.1", - "react-native-invertible-scroll-view": "1.1.0", - "react-native-lightbox": "0.7.0", - "react-native-parsed-text": "0.0.19", - "shallowequal": "1.0.2", - "uuid": "3.1.0" - }, - "dependencies": { - "md5": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/md5/download/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" - } - }, - "prop-types": { - "version": "15.5.10", - "resolved": "http://registry.npm.taobao.org/prop-types/download/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", - "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1" - } - } - } - }, - "react-native-image-crop-picker": { - "version": "0.20.0", - "resolved": "http://registry.npm.taobao.org/react-native-image-crop-picker/download/react-native-image-crop-picker-0.20.0.tgz", - "integrity": "sha1-KbjfNesX/3rWFSTsCYMvSeVSQn0=" - }, - "react-native-invertible-scroll-view": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/react-native-invertible-scroll-view/download/react-native-invertible-scroll-view-1.1.0.tgz", - "integrity": "sha1-v9UKP11myhJjm3x6mETO3dHRaJA=", - "requires": { - "create-react-class": "15.6.2", - "prop-types": "15.6.0", - "react-clone-referenced-element": "1.0.1", - "react-native-scrollable-mixin": "1.0.1" - } - }, - "react-native-iphone-x-helper": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.0.2.tgz", - "integrity": "sha512-5FYNC4kTi/YK86l+r8GQ0xgsSL2tleCQ5Yppu1+ARbnm2qGRmDoJTGSNsWBAWa8FP1ORyhMjxi18IlvSRKaI2g==" - }, - "react-native-keyboard-aware-scroll-view": { - "version": "0.4.1", - "resolved": "http://registry.npm.taobao.org/react-native-keyboard-aware-scroll-view/download/react-native-keyboard-aware-scroll-view-0.4.1.tgz", - "integrity": "sha1-vahsvjzfYMVyqV5+D7rGNbyc5m0=", - "requires": { - "prop-types": "15.6.0", - "react-native-iphone-x-helper": "1.0.2" - } - }, - "react-native-lightbox": { - "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/react-native-lightbox/download/react-native-lightbox-0.7.0.tgz", - "integrity": "sha1-5StNf8wUH1nXsj8BgN5TXjWyDsk=", - "requires": { - "prop-types": "15.6.0" - } - }, - "react-native-message-bar": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/react-native-message-bar/download/react-native-message-bar-1.6.0.tgz", - "integrity": "sha1-eWI+iWVUdSFpJwkHcbAjhha28cc=" - }, - "react-native-mock": { - "version": "0.2.9", - "resolved": "http://registry.npm.taobao.org/react-native-mock/download/react-native-mock-0.2.9.tgz", - "integrity": "sha1-4hPHFKIPUyug3wNHQgXlJ2aDwpg=", - "dev": true, - "requires": { - "cubic-bezier": "0.1.2", - "invariant": "2.2.2", - "keymirror": "0.1.1", - "raf": "3.4.0", - "react-addons-create-fragment": "15.6.2", - "react-addons-perf": "15.4.2", - "react-addons-pure-render-mixin": "15.6.2", - "react-addons-test-utils": "15.6.2", - "react-addons-update": "15.6.2", - "react-dom": "15.6.2", - "react-timer-mixin": "0.13.3", - "warning": "2.1.0" - } - }, - "react-native-parsed-text": { - "version": "0.0.19", - "resolved": "http://registry.npm.taobao.org/react-native-parsed-text/download/react-native-parsed-text-0.0.19.tgz", - "integrity": "sha1-GqzKb57oL5OfYO+YXfkMl71VxFo=", - "requires": { - "prop-types": "15.6.0" - } - }, - "react-native-safari-view": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/react-native-safari-view/-/react-native-safari-view-2.1.0.tgz", - "integrity": "sha1-HgzRLGK855vBdZx+KBZGsIthyVk=" - }, - "react-native-safe-area-view": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.6.0.tgz", - "integrity": "sha512-aMloMb1Ds+HA/e4IxWUWwtQ41NV3sbpR/54zFhdIVTnzZq/ziX7ea9hddxMMx0RjvhJ7C0BznryWdVjUa/rvDg==", - "requires": { - "hoist-non-react-statics": "2.3.1" - } - }, - "react-native-scrollable-mixin": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/react-native-scrollable-mixin/download/react-native-scrollable-mixin-1.0.1.tgz", - "integrity": "sha1-NKMhZ7ZCSFlBVP0NaosD8idAVI4=" - }, - "react-native-scrollable-tab-view": { - "version": "0.8.0", - "resolved": "http://registry.npm.taobao.org/react-native-scrollable-tab-view/download/react-native-scrollable-tab-view-0.8.0.tgz", - "integrity": "sha1-XLH8/OB79TCjyBq1H8UHEUTtrFw=", - "requires": { - "create-react-class": "15.6.2", - "prop-types": "15.6.0", - "react-timer-mixin": "0.13.3" - } - }, - "react-native-search-bar": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/react-native-search-bar/download/react-native-search-bar-3.1.0.tgz", - "integrity": "sha1-SOjMgemUfmBSbNscwiVEUcblmMk=", - "requires": { - "prop-types": "15.6.0" - } - }, - "react-native-smart-emoji-picker": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/react-native-smart-emoji-picker/-/react-native-smart-emoji-picker-0.1.0.tgz", - "integrity": "sha1-SYGD7RMi6UP/joZeqcoHkNg1sPQ=", - "requires": { - "react-native-scrollable-tab-view": "0.8.0" - } - }, - "react-native-smart-timer-enhance": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/react-native-smart-timer-enhance/download/react-native-smart-timer-enhance-1.0.3.tgz", - "integrity": "sha1-R93Bm+WmwZGERJA5SV8lVGvNlP4=" - }, - "react-native-sticky-keyboard-accessory": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/react-native-sticky-keyboard-accessory/-/react-native-sticky-keyboard-accessory-0.1.1.tgz", - "integrity": "sha1-F2wpkyp+kptq8ULC1WUea5zrVH4=", - "requires": { - "react-native-iphone-x-helper": "1.0.2" - }, - "dependencies": { - "react-native-iphone-x-helper": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.0.2.tgz", - "integrity": "sha512-5FYNC4kTi/YK86l+r8GQ0xgsSL2tleCQ5Yppu1+ARbnm2qGRmDoJTGSNsWBAWa8FP1ORyhMjxi18IlvSRKaI2g==" - } - } - }, - "react-native-tab-view": { - "version": "0.0.74", - "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.74.tgz", - "integrity": "sha512-aCrLugxt5LqdSk0pHqu/nDGZMIM3NvxVcXb464coY7ecWgem6IxQ8riO3QXPJhXZ7HaayfofBJF9w4uIWt/AoQ==", - "requires": { - "prop-types": "15.6.0" - } - }, - "react-native-vector-icons": { - "version": "4.4.3", - "resolved": "http://registry.npm.taobao.org/react-native-vector-icons/download/react-native-vector-icons-4.4.3.tgz", - "integrity": "sha1-noR7jEMqF+Xg/9YMzwnzESoYud8=", - "requires": { - "lodash": "4.17.4", - "prop-types": "15.6.0", - "yargs": "8.0.2" - }, - "dependencies": { - "yargs": { - "version": "8.0.2", - "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - } - } - } - }, - "react-navigation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.0.3.tgz", - "integrity": "sha512-A7fBnkKZbWqmKePw76WI/KGUDRJLSGeuh7ueUSfosup19X7+TxJFK3GcHaykYZSmBGhjzZqAqPzNfojS1tvGMg==", - "requires": { - "clamp": "1.0.1", - "hoist-non-react-statics": "2.3.1", - "path-to-regexp": "1.7.0", - "prop-types": "15.6.0", - "react-native-drawer-layout-polyfill": "1.3.2", - "react-native-safe-area-view": "0.6.0", - "react-native-tab-view": "0.0.74" - } - }, - "react-proxy": { - "version": "1.1.8", - "resolved": "http://registry.npm.taobao.org/react-proxy/download/react-proxy-1.1.8.tgz", - "integrity": "sha1-nb/Z2SdSjDqp9ETkVYw3gwq4wmo=", - "requires": { - "lodash": "4.17.4", - "react-deep-force-update": "1.1.1" - } - }, - "react-redux": { - "version": "5.0.6", - "resolved": "http://registry.npm.taobao.org/react-redux/download/react-redux-5.0.6.tgz", - "integrity": "sha1-I+06T5hjWdaLUhLqqmgeYNZXSUY=", - "requires": { - "hoist-non-react-statics": "2.3.1", - "invariant": "2.2.2", - "lodash": "4.17.4", - "lodash-es": "4.17.4", - "loose-envify": "1.3.1", - "prop-types": "15.6.0" - } - }, - "react-timer-mixin": { - "version": "0.13.3", - "resolved": "http://registry.npm.taobao.org/react-timer-mixin/download/react-timer-mixin-0.13.3.tgz", - "integrity": "sha1-Dai5+AfsB9w+hU0ILHN8ZWBbPSI=" - }, - "react-transform-hmr": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/react-transform-hmr/download/react-transform-hmr-1.0.4.tgz", - "integrity": "sha1-4aQL0Krvxy6N/Xp82gmvhQZjl7s=", - "requires": { - "global": "4.3.2", - "react-proxy": "1.1.8" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/readline2/download/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "http://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, - "reduce-reducers": { - "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/reduce-reducers/download/reduce-reducers-0.1.2.tgz", - "integrity": "sha1-+htHGLxSkqcd3R5dg5yb6pdw8Us=" - }, - "redux": { - "version": "3.3.1", - "resolved": "http://registry.npm.taobao.org/redux/download/redux-3.3.1.tgz", - "integrity": "sha1-cW34AEeG3q8ByTrjlshPwQQeQks=", - "requires": { - "lodash": "4.17.4", - "lodash-es": "4.17.4", - "loose-envify": "1.3.1" - } - }, - "redux-actions": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/redux-actions/download/redux-actions-1.2.1.tgz", - "integrity": "sha1-ZJcR2I9J8d3lvFoc6ozuxbVNkYE=", - "requires": { - "invariant": "2.2.2", - "lodash": "4.17.4", - "reduce-reducers": "0.1.2" - } - }, - "redux-saga": { - "version": "0.12.0", - "resolved": "http://registry.npm.taobao.org/redux-saga/download/redux-saga-0.12.0.tgz", - "integrity": "sha1-S2FF5vjDOmCC99GPMKtdKQHmIeg=" - }, - "regenerate": { - "version": "1.3.3", - "resolved": "http://registry.npm.taobao.org/regenerate/download/regenerate-1.3.3.tgz", - "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "http://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "http://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.10.1.tgz", - "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "http://registry.npm.taobao.org/regex-cache/download/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/regexpu-core/download/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "requires": { - "regenerate": "1.3.3", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/regjsgen/download/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "http://registry.npm.taobao.org/regjsparser/download/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "http://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/repeating/download/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "1.0.2" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/replace-ext/download/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" - }, - "request": { - "version": "2.83.0", - "resolved": "http://registry.npm.taobao.org/request/download/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" - }, - "dependencies": { - "qs": { - "version": "6.5.1", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/require-main-filename/download/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/require-uncached/download/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" - } - }, - "resolve": { - "version": "1.5.0", - "resolved": "http://registry.npm.taobao.org/resolve/download/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "response-time": { - "version": "2.3.2", - "resolved": "http://registry.npm.taobao.org/response-time/download/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "requires": { - "depd": "1.1.1", - "on-headers": "1.0.1" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - } - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "requires": { - "glob": "7.1.2" - } - }, - "rndm": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/rndm/download/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" - }, - "run-async": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/run-async/download/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "http://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "http://registry.npm.taobao.org/rx-lite-aggregates/download/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" - }, - "sane": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/sane/download/sane-2.2.0.tgz", - "integrity": "sha1-1tLi/KsA49KDyTuRK3w6IIRvHVY=", - "requires": { - "anymatch": "1.3.2", - "exec-sh": "0.2.1", - "fb-watchman": "2.0.0", - "fsevents": "1.1.3", - "minimatch": "3.0.4", - "minimist": "1.2.0", - "walker": "1.0.7", - "watch": "0.18.0" - } - }, - "sax": { - "version": "1.1.6", - "resolved": "http://registry.npm.taobao.org/sax/download/sax-1.1.6.tgz", - "integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA=" - }, - "semver": { - "version": "5.4.1", - "resolved": "http://registry.npm.taobao.org/semver/download/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" - }, - "send": { - "version": "0.13.2", - "resolved": "http://registry.npm.taobao.org/send/download/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", - "requires": { - "debug": "2.2.0", - "depd": "1.1.1", - "destroy": "1.0.4", - "escape-html": "1.0.3", - "etag": "1.7.0", - "fresh": "0.3.0", - "http-errors": "1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "2.3.0", - "range-parser": "1.0.3", - "statuses": "1.2.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "depd": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "mime": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - }, - "statuses": { - "version": "1.2.1", - "resolved": "http://registry.npm.taobao.org/statuses/download/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" - } - } - }, - "serve-favicon": { - "version": "2.3.2", - "resolved": "http://registry.npm.taobao.org/serve-favicon/download/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "requires": { - "etag": "1.7.0", - "fresh": "0.3.0", - "ms": "0.7.2", - "parseurl": "1.3.2" - }, - "dependencies": { - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" - } - } - }, - "serve-index": { - "version": "1.7.3", - "resolved": "http://registry.npm.taobao.org/serve-index/download/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", - "requires": { - "accepts": "1.2.13", - "batch": "0.5.3", - "debug": "2.2.0", - "escape-html": "1.0.3", - "http-errors": "1.3.1", - "mime-types": "2.1.17", - "parseurl": "1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - } - } - }, - "serve-static": { - "version": "1.10.3", - "resolved": "http://registry.npm.taobao.org/serve-static/download/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "requires": { - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.13.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "shallowequal": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/shallowequal/download/shallowequal-1.0.2.tgz", - "integrity": "sha1-FWHb3vuMAUCBADGQhXZNo/z4P48=" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "shell-quote": { - "version": "1.6.1", - "resolved": "http://registry.npm.taobao.org/shell-quote/download/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "requires": { - "array-filter": "0.0.1", - "array-map": "0.0.0", - "array-reduce": "0.0.0", - "jsonify": "0.0.0" - } - }, - "shelljs": { - "version": "0.5.3", - "resolved": "http://registry.npm.taobao.org/shelljs/download/shelljs-0.5.3.tgz", - "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", - "dev": true - }, - "shellwords": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/shellwords/download/shellwords-0.1.1.tgz", - "integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-plist": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/simple-plist/download/simple-plist-0.2.1.tgz", - "integrity": "sha1-cXZts1IyaSjPOoByQrp2IyJjZyM=", - "requires": { - "bplist-creator": "0.0.7", - "bplist-parser": "0.1.1", - "plist": "2.0.1" - }, - "dependencies": { - "base64-js": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-1.1.2.tgz", - "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=" - }, - "plist": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/plist/download/plist-2.0.1.tgz", - "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", - "requires": { - "base64-js": "1.1.2", - "xmlbuilder": "8.2.2", - "xmldom": "0.1.27" - } - }, - "xmlbuilder": { - "version": "8.2.2", - "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" - } - } - }, - "slash": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "http://registry.npm.taobao.org/slice-ansi/download/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "slide": { - "version": "1.1.6", - "resolved": "http://registry.npm.taobao.org/slide/download/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" - }, - "sntp": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", - "requires": { - "hoek": "4.2.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "http://registry.npm.taobao.org/source-map-support/download/source-map-support-0.4.18.tgz", - "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", - "requires": { - "source-map": "0.5.7" - } - }, - "sparkles": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/sparkles/download/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=" - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/spdx-correct/download/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "http://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.13.1", - "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - } - }, - "stacktrace-parser": { - "version": "0.1.4", - "resolved": "http://registry.npm.taobao.org/stacktrace-parser/download/stacktrace-parser-0.1.4.tgz", - "integrity": "sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4=" - }, - "statuses": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/statuses/download/statuses-1.4.0.tgz", - "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" - }, - "stream-buffers": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/stream-buffers/download/stream-buffers-2.2.0.tgz", - "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" - }, - "stream-counter": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/stream-counter/download/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", - "requires": { - "readable-stream": "1.1.14" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "http://registry.npm.taobao.org/stringstream/download/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "sync-exec": { - "version": "0.6.2", - "resolved": "http://registry.npm.taobao.org/sync-exec/download/sync-exec-0.6.2.tgz", - "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", - "optional": true - }, - "table": { - "version": "3.8.3", - "resolved": "http://registry.npm.taobao.org/table/download/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.4", - "slice-ansi": "0.0.4", - "string-width": "2.1.1" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - } - } - }, - "temp": { - "version": "0.8.3", - "resolved": "http://registry.npm.taobao.org/temp/download/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "requires": { - "os-tmpdir": "1.0.2", - "rimraf": "2.2.8" - }, - "dependencies": { - "rimraf": { - "version": "2.2.8", - "resolved": "http://registry.npm.taobao.org/rimraf/download/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "throat": { - "version": "4.1.0", - "resolved": "http://registry.npm.taobao.org/throat/download/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" - }, - "through": { - "version": "2.3.8", - "resolved": "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/through2/download/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/time-stamp/download/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "http://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "tmpl": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/tmpl/download/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "requires": { - "punycode": "1.4.1" - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/trim-right/download/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" - }, - "tsscmp": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "http://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2" - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/type-detect/download/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.15", - "resolved": "http://registry.npm.taobao.org/type-is/download/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.17" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "http://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "ua-parser-js": { - "version": "0.7.17", - "resolved": "http://registry.npm.taobao.org/ua-parser-js/download/ua-parser-js-0.7.17.tgz", - "integrity": "sha1-6exflJi57JEOeuOsYmqAXE0J7Kw=" - }, - "uglify-es": { - "version": "3.3.5", - "resolved": "http://registry.npm.taobao.org/uglify-es/download/uglify-es-3.3.5.tgz", - "integrity": "sha1-z35pXagZmfhRlrFeKXiGLxMhL4g=", - "requires": { - "commander": "2.12.2", - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" - } - } - }, - "uid-safe": { - "version": "2.1.4", - "resolved": "http://registry.npm.taobao.org/uid-safe/download/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "requires": { - "random-bytes": "1.0.0" - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/ultron/download/ultron-1.1.1.tgz", - "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "user-home": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/user-home/download/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" - }, - "uuid": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } - }, - "vary": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" - }, - "verror": { - "version": "1.10.0", - "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - } - }, - "vhost": { - "version": "3.0.2", - "resolved": "http://registry.npm.taobao.org/vhost/download/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=" - }, - "vinyl": { - "version": "0.5.3", - "resolved": "http://registry.npm.taobao.org/vinyl/download/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "walker": { - "version": "1.0.7", - "resolved": "http://registry.npm.taobao.org/walker/download/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "requires": { - "makeerror": "1.0.11" - } - }, - "warning": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/warning/download/warning-2.1.0.tgz", - "integrity": "sha1-ISINnGOvx3qMkhEeARr3Bc4MaQE=", - "dev": true, - "requires": { - "loose-envify": "1.3.1" - } - }, - "watch": { - "version": "0.18.0", - "resolved": "http://registry.npm.taobao.org/watch/download/watch-0.18.0.tgz", - "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "requires": { - "exec-sh": "0.2.1", - "minimist": "1.2.0" - } - }, - "whatwg-fetch": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/whatwg-fetch/download/whatwg-fetch-2.0.3.tgz", - "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" - }, - "which": { - "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/which/download/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "win-release": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/win-release/download/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "requires": { - "semver": "5.4.1" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "worker-farm": { - "version": "1.5.2", - "resolved": "http://registry.npm.taobao.org/worker-farm/download/worker-farm-1.5.2.tgz", - "integrity": "sha1-MrMS5dw9XUXXnvRKzCWHSRzXKa4=", - "requires": { - "errno": "0.1.6", - "xtend": "4.0.1" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/write/download/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "0.5.1" - } - }, - "write-file-atomic": { - "version": "1.3.4", - "resolved": "http://registry.npm.taobao.org/write-file-atomic/download/write-file-atomic-1.3.4.tgz", - "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" - } - }, - "ws": { - "version": "1.1.5", - "resolved": "http://registry.npm.taobao.org/ws/download/ws-1.1.5.tgz", - "integrity": "sha1-y9nm514J/F0skAFfIfDECHXg3VE=", - "requires": { - "options": "0.0.6", - "ultron": "1.0.2" - }, - "dependencies": { - "ultron": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/ultron/download/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" - } - } - }, - "xcode": { - "version": "0.9.3", - "resolved": "http://registry.npm.taobao.org/xcode/download/xcode-0.9.3.tgz", - "integrity": "sha1-kQqJwWrubMC0LKgFptC0z4chHPM=", - "requires": { - "pegjs": "0.10.0", - "simple-plist": "0.2.1", - "uuid": "3.0.1" - }, - "dependencies": { - "uuid": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" - } - } - }, - "xmlbuilder": { - "version": "4.0.0", - "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-4.0.0.tgz", - "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=", - "requires": { - "lodash": "3.10.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, - "xmldoc": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/xmldoc/download/xmldoc-0.4.0.tgz", - "integrity": "sha1-0lciS+g5PqrL+DfvIn/Y7CWzaIg=", - "requires": { - "sax": "1.1.6" - } - }, - "xmldom": { - "version": "0.1.27", - "resolved": "http://registry.npm.taobao.org/xmldom/download/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" - }, - "xpipe": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/xpipe/download/xpipe-1.0.5.tgz", - "integrity": "sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "http://registry.npm.taobao.org/y18n/download/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "yargs": { - "version": "9.0.1", - "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "requires": { - "camelcase": "4.1.0" - } - } - } -} diff --git a/package.json b/package.json index c1183e6..8ea7b80 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,12 @@ "react-native-image-crop-picker": "0.20.0", "react-native-iphone-x-helper": "1.0.2", "react-native-keyboard-aware-scroll-view": "0.4.1", - "react-native-message-bar": "1.6.0", + "react-native-message-bar": "^1.6.0", "react-native-safari-view": "2.1.0", "react-native-scrollable-tab-view": "0.8.0", "react-native-search-bar": "3.1.0", "react-native-smart-emoji-picker": "0.1.0", - "react-native-smart-timer-enhance": "^1.0.3", + "react-native-smart-timer-enhance": "1.0.3", "react-native-sticky-keyboard-accessory": "0.1.1", "react-native-vector-icons": "4.4.3", "react-navigation": "1.0.3", @@ -44,16 +44,16 @@ "redux-saga": "0.12.0" }, "devDependencies": { - "babel": "6.5.2", - "babel-core": "6.22.1", - "babel-eslint": "6.0.0-beta.6", - "babel-preset-react-native": "1.9.1", - "chai": "3.5.0", - "enzyme": "2.7.0", - "eslint": "2.4.0", - "eslint-plugin-react": "4.2.3", - "mocha": "3.2.0", - "react-native-mock": "0.2.9" + "babel": "^6.23.0", + "babel-core": "^6.26.3", + "babel-eslint": "^8.2.6", + "babel-preset-react-native": "^4.0.0", + "chai": "^4.1.2", + "enzyme": "^3.3.0", + "eslint": "^5.2.0", + "eslint-plugin-react": "^7.10.0", + "mocha": "^5.2.0", + "react-native-mock": "^0.3.1" }, "license": "MIT" } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..69f56c9 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,5227 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" + dependencies: + "@babel/highlight" "7.0.0-beta.44" + +"@babel/generator@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" + dependencies: + "@babel/types" "7.0.0-beta.44" + jsesc "^2.5.1" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-function-name@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.44" + "@babel/template" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + +"@babel/helper-get-function-arity@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" + dependencies: + "@babel/types" "7.0.0-beta.44" + +"@babel/helper-split-export-declaration@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" + dependencies: + "@babel/types" "7.0.0-beta.44" + +"@babel/highlight@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/template@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + lodash "^4.2.0" + +"@babel/traverse@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/generator" "7.0.0-beta.44" + "@babel/helper-function-name" "7.0.0-beta.44" + "@babel/helper-split-export-declaration" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + debug "^3.1.0" + globals "^11.1.0" + invariant "^2.2.0" + lodash "^4.2.0" + +"@babel/types@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + +"@expo/react-native-action-sheet@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@expo/react-native-action-sheet/-/react-native-action-sheet-1.0.2.tgz#abdfb21cbefec6147c6ee8b8fb725287cbd2e696" + dependencies: + hoist-non-react-statics "^2.2.2" + prop-types "^15.5.10" + +"@types/node@*": + version "10.5.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.3.tgz#5bcfaf088ad17894232012877669634c06b20cc5" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +absolute-path@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7" + +accepts@~1.2.12, accepts@~1.2.13: + version "1.2.13" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" + dependencies: + mime-types "~2.1.6" + negotiator "0.5.3" + +accepts@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + +acorn-jsx@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" + dependencies: + acorn "^5.0.3" + +acorn@^5.0.3, acorn@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + +ajv-keywords@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ajv@^6.0.1, ajv@^6.5.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.1" + +ansi-colors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + dependencies: + ansi-wrap "^0.1.0" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + dependencies: + ansi-wrap "0.1.0" + +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +ansi-wrap@0.1.0, ansi-wrap@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + +ansi@^0.3.0, ansi@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +apsl-react-native-button@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/apsl-react-native-button/-/apsl-react-native-button-3.1.0.tgz#8fe6ebf734cc5f1006c6eb1d54370abc3c3833f5" + dependencies: + lodash.isequal "^4.1.4" + prop-types "^15.5.10" + +arch@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +art@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assertion-error@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + +async@^2.4.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + dependencies: + lodash "^4.17.10" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.24.1, babel-core@^6.26.0, babel-core@^6.26.3, babel-core@^6.7.2: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-eslint@^8.2.6: + version "8.2.6" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.6.tgz#6270d0c73205628067c0f7ae1693a9e797acefd9" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/traverse" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + eslint-scope "3.7.1" + eslint-visitor-keys "^1.0.0" + +babel-generator@^6.24.1, babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.16.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.5.0, babel-plugin-check-es2015-constants@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-external-helpers@^6.18.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-react-transform@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" + dependencies: + lodash "^4.6.1" + +babel-plugin-syntax-async-functions@^6.5.0, babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-class-properties@^6.5.0, babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.5.0, babel-plugin-syntax-flow@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.5.0, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.5.0, babel-plugin-syntax-trailing-function-commas@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz#19ec36cb1486b59f9f468adfa42ce13908ca2999" + dependencies: + babel-helper-remap-async-to-generator "^6.16.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-class-properties@^6.18.0, babel-plugin-transform-class-properties@^6.5.0, babel-plugin-transform-class-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-arrow-functions@^6.5.0, babel-plugin-transform-es2015-arrow-functions@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.5.0, babel-plugin-transform-es2015-block-scoping@^6.8.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.5.0, babel-plugin-transform-es2015-classes@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.5.0, babel-plugin-transform-es2015-computed-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@6.x, babel-plugin-transform-es2015-destructuring@^6.5.0, babel-plugin-transform-es2015-destructuring@^6.8.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-for-of@^6.5.0, babel-plugin-transform-es2015-for-of@^6.8.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@6.x, babel-plugin-transform-es2015-function-name@^6.5.0, babel-plugin-transform-es2015-function-name@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.5.0, babel-plugin-transform-es2015-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-commonjs@6.x, babel-plugin-transform-es2015-modules-commonjs@^6.5.0, babel-plugin-transform-es2015-modules-commonjs@^6.8.0: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-object-super@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@6.x, babel-plugin-transform-es2015-parameters@^6.5.0, babel-plugin-transform-es2015-parameters@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@6.x, babel-plugin-transform-es2015-shorthand-properties@^6.5.0, babel-plugin-transform-es2015-shorthand-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@6.x, babel-plugin-transform-es2015-spread@^6.5.0, babel-plugin-transform-es2015-spread@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@6.x: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.5.0, babel-plugin-transform-es2015-template-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@6.x: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-es3-member-expression-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz#733d3444f3ecc41bef8ed1a6a4e09657b8969ebb" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es3-property-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz#b2078d5842e22abf40f73e8cde9cd3711abd5758" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-exponentiation-operator@^6.5.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.21.0, babel-plugin-transform-flow-strip-types@^6.5.0, babel-plugin-transform-flow-strip-types@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-object-assign@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.20.2, babel-plugin-transform-object-rest-spread@^6.5.0, babel-plugin-transform-object-rest-spread@^6.8.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-react-display-name@^6.5.0, babel-plugin-transform-react-display-name@^6.8.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.5.0, babel-plugin-transform-react-jsx@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.5.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-es2015-node@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015-node/-/babel-preset-es2015-node-6.1.1.tgz#60b23157024b0cfebf3a63554cb05ee035b4e55f" + dependencies: + babel-plugin-transform-es2015-destructuring "6.x" + babel-plugin-transform-es2015-function-name "6.x" + babel-plugin-transform-es2015-modules-commonjs "6.x" + babel-plugin-transform-es2015-parameters "6.x" + babel-plugin-transform-es2015-shorthand-properties "6.x" + babel-plugin-transform-es2015-spread "6.x" + babel-plugin-transform-es2015-sticky-regex "6.x" + babel-plugin-transform-es2015-unicode-regex "6.x" + semver "5.x" + +babel-preset-fbjs@^2.1.2, babel-preset-fbjs@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-2.2.0.tgz#c25b879a914feefd964052b1bce4c90ee915023a" + dependencies: + babel-plugin-check-es2015-constants "^6.8.0" + babel-plugin-syntax-class-properties "^6.8.0" + babel-plugin-syntax-flow "^6.8.0" + babel-plugin-syntax-jsx "^6.8.0" + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-plugin-syntax-trailing-function-commas "^6.8.0" + babel-plugin-transform-class-properties "^6.8.0" + babel-plugin-transform-es2015-arrow-functions "^6.8.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.8.0" + babel-plugin-transform-es2015-block-scoping "^6.8.0" + babel-plugin-transform-es2015-classes "^6.8.0" + babel-plugin-transform-es2015-computed-properties "^6.8.0" + babel-plugin-transform-es2015-destructuring "^6.8.0" + babel-plugin-transform-es2015-for-of "^6.8.0" + babel-plugin-transform-es2015-function-name "^6.8.0" + babel-plugin-transform-es2015-literals "^6.8.0" + babel-plugin-transform-es2015-modules-commonjs "^6.8.0" + babel-plugin-transform-es2015-object-super "^6.8.0" + babel-plugin-transform-es2015-parameters "^6.8.0" + babel-plugin-transform-es2015-shorthand-properties "^6.8.0" + babel-plugin-transform-es2015-spread "^6.8.0" + babel-plugin-transform-es2015-template-literals "^6.8.0" + babel-plugin-transform-es3-member-expression-literals "^6.8.0" + babel-plugin-transform-es3-property-literals "^6.8.0" + babel-plugin-transform-flow-strip-types "^6.8.0" + babel-plugin-transform-object-rest-spread "^6.8.0" + babel-plugin-transform-react-display-name "^6.8.0" + babel-plugin-transform-react-jsx "^6.8.0" + +babel-preset-react-native@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-4.0.0.tgz#3df80dd33a453888cdd33bdb87224d17a5d73959" + dependencies: + babel-plugin-check-es2015-constants "^6.5.0" + babel-plugin-react-transform "^3.0.0" + babel-plugin-syntax-async-functions "^6.5.0" + babel-plugin-syntax-class-properties "^6.5.0" + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-syntax-flow "^6.5.0" + babel-plugin-syntax-jsx "^6.5.0" + babel-plugin-syntax-trailing-function-commas "^6.5.0" + babel-plugin-transform-class-properties "^6.5.0" + babel-plugin-transform-es2015-arrow-functions "^6.5.0" + babel-plugin-transform-es2015-block-scoping "^6.5.0" + babel-plugin-transform-es2015-classes "^6.5.0" + babel-plugin-transform-es2015-computed-properties "^6.5.0" + babel-plugin-transform-es2015-destructuring "^6.5.0" + babel-plugin-transform-es2015-for-of "^6.5.0" + babel-plugin-transform-es2015-function-name "^6.5.0" + babel-plugin-transform-es2015-literals "^6.5.0" + babel-plugin-transform-es2015-modules-commonjs "^6.5.0" + babel-plugin-transform-es2015-parameters "^6.5.0" + babel-plugin-transform-es2015-shorthand-properties "^6.5.0" + babel-plugin-transform-es2015-spread "^6.5.0" + babel-plugin-transform-es2015-template-literals "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.5.0" + babel-plugin-transform-object-assign "^6.5.0" + babel-plugin-transform-object-rest-spread "^6.5.0" + babel-plugin-transform-react-display-name "^6.5.0" + babel-plugin-transform-react-jsx "^6.5.0" + babel-plugin-transform-react-jsx-source "^6.5.0" + babel-plugin-transform-regenerator "^6.5.0" + babel-template "^6.24.1" + react-transform-hmr "^1.0.4" + +babel-register@^6.24.1, babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babel@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel/-/babel-6.23.0.tgz#d0d1e7d803e974765beea3232d4e153c0efb90f4" + +babylon@7.0.0-beta.44: + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + +base64-js@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.1.2.tgz#d6400cac1c4c660976d90d07a04351d89395f5e8" + +base64-js@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + +base64-url@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +basic-auth-connect@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" + +basic-auth@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" + +batch@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +big-integer@^1.6.7: + version "1.6.32" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.32.tgz#5867458b25ecd5bcb36b627c30bb501a13c07e89" + +body-parser@~1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" + dependencies: + bytes "2.1.0" + content-type "~1.0.1" + debug "~2.2.0" + depd "~1.0.1" + http-errors "~1.3.1" + iconv-lite "0.4.11" + on-finished "~2.3.0" + qs "4.0.0" + raw-body "~2.1.2" + type-is "~1.6.6" + +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + +bplist-creator@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.7.tgz#37df1536092824b87c42f957b01344117372ae45" + dependencies: + stream-buffers "~2.2.0" + +bplist-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.1.1.tgz#d60d5dcc20cba6dc7e1f299b35d3e1f95dafbae6" + dependencies: + big-integer "^1.6.7" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + +bser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +bytes@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" + +bytes@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +capture-exit@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" + dependencies: + rsvp "^3.3.3" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + +chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + +charenc@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + +check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.2" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +clamp@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/clamp/-/clamp-1.0.1.tgz#66a0e64011816e37196828fdc8c8c147312c8634" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +clipboardy@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" + dependencies: + arch "^2.1.0" + execa "^0.8.0" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + +colors@0.5.x: + version "0.5.1" + resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774" + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +commander@^2.9.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +compressible@~2.0.5: + version "2.0.14" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7" + dependencies: + mime-db ">= 1.34.0 < 2" + +compression@~1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395" + dependencies: + accepts "~1.2.12" + bytes "2.1.0" + compressible "~2.0.5" + debug "~2.2.0" + on-headers "~1.0.0" + vary "~1.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect-timeout@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/connect-timeout/-/connect-timeout-1.6.2.tgz#de9a5ec61e33a12b6edaab7b5f062e98c599b88e" + dependencies: + debug "~2.2.0" + http-errors "~1.3.1" + ms "0.7.1" + on-headers "~1.0.0" + +connect@^2.8.3: + version "2.30.2" + resolved "https://registry.yarnpkg.com/connect/-/connect-2.30.2.tgz#8da9bcbe8a054d3d318d74dfec903b5c39a1b609" + dependencies: + basic-auth-connect "1.0.0" + body-parser "~1.13.3" + bytes "2.1.0" + compression "~1.5.2" + connect-timeout "~1.6.2" + content-type "~1.0.1" + cookie "0.1.3" + cookie-parser "~1.3.5" + cookie-signature "1.0.6" + csurf "~1.8.3" + debug "~2.2.0" + depd "~1.0.1" + errorhandler "~1.4.2" + express-session "~1.11.3" + finalhandler "0.4.0" + fresh "0.3.0" + http-errors "~1.3.1" + method-override "~2.3.5" + morgan "~1.6.1" + multiparty "3.3.2" + on-headers "~1.0.0" + parseurl "~1.3.0" + pause "0.1.0" + qs "4.0.0" + response-time "~2.3.1" + serve-favicon "~2.3.0" + serve-index "~1.7.2" + serve-static "~1.10.0" + type-is "~1.6.6" + utils-merge "1.0.0" + vhost "~3.0.1" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +content-type@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +cookie-parser@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +crc@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.3.0.tgz#fa622e1bc388bf257309082d6b65200ce67090ba" + +create-react-class@^15.5.2, create-react-class@^15.6.0, create-react-class@^15.6.2: + version "15.6.3" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypt@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + +csrf@~3.0.0: + version "3.0.6" + resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.0.6.tgz#b61120ddceeafc91e76ed5313bb5c0b2667b710a" + dependencies: + rndm "1.2.0" + tsscmp "1.0.5" + uid-safe "2.1.4" + +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + +csurf@~1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.8.3.tgz#23f2a13bf1d8fce1d0c996588394442cba86a56a" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + csrf "~3.0.0" + http-errors "~1.3.1" + +cubic-bezier@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cubic-bezier/-/cubic-bezier-0.1.2.tgz#d4970942002e45372e0aa92db657e39eaf6824d7" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + dependencies: + type-detect "^4.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + +depd@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" + +depd@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + +discontinuous-range@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + +dom-serializer@0, dom-serializer@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + dependencies: + dom-serializer "0" + domelementtype "1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +envinfo@^3.0.0: + version "3.11.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-3.11.1.tgz#45968faf5079aa797b7dcdc3b123f340d4529e1c" + dependencies: + clipboardy "^1.2.2" + glob "^7.1.2" + minimist "^1.2.0" + os-name "^2.0.1" + which "^1.2.14" + +enzyme@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.3.0.tgz#0971abd167f2d4bf3f5bd508229e1c4b6dc50479" + dependencies: + cheerio "^1.0.0-rc.2" + function.prototype.name "^1.0.3" + has "^1.0.1" + is-boolean-object "^1.0.0" + is-callable "^1.1.3" + is-number-object "^1.0.3" + is-string "^1.0.4" + is-subset "^0.1.1" + lodash "^4.17.4" + object-inspect "^1.5.0" + object-is "^1.0.1" + object.assign "^4.1.0" + object.entries "^1.0.4" + object.values "^1.0.4" + raf "^3.4.0" + rst-selector-parser "^2.2.3" + +errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +errorhandler@~1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" + dependencies: + accepts "~1.3.0" + escape-html "~1.0.3" + +es-abstract@^1.10.0, es-abstract@^1.6.1, es-abstract@^1.7.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.45" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.45.tgz#0bfdf7b473da5919d5adf3bd25ceb754fccc3653" + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + next-tick "1" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +escape-html@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +eslint-plugin-react@^7.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz#af5c1fef31c4704db02098f9be18202993828b50" + dependencies: + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.0.1" + prop-types "^15.6.2" + +eslint-scope@3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" + +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + +eslint@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.2.0.tgz#3901ae249195d473e633c4acbc370068b1c964dc" + dependencies: + ajv "^6.5.0" + babel-code-frame "^6.26.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^4.0.0" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^4.0.0" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.2" + imurmurhash "^0.1.4" + inquirer "^5.2.0" + is-resolvable "^1.1.0" + js-yaml "^3.11.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.5" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.1.0" + require-uncached "^1.0.3" + semver "^5.5.0" + string.prototype.matchall "^2.0.0" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^4.0.3" + text-table "^0.2.0" + +espree@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" + dependencies: + acorn "^5.6.0" + acorn-jsx "^4.1.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + +event-target-shim@^1.0.5: + version "1.1.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491" + +exec-sh@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" + dependencies: + merge "^1.2.0" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +express-session@~1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + crc "3.3.0" + debug "~2.2.0" + depd "~1.0.1" + on-headers "~1.0.0" + parseurl "~1.3.0" + uid-safe "~2.0.0" + utils-merge "1.0.0" + +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + dependencies: + kind-of "^1.1.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +external-editor@^2.0.4, external-editor@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fancy-log@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + time-stamp "^1.0.0" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fb-watchman@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" + dependencies: + bser "^2.0.0" + +fbjs-scripts@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/fbjs-scripts/-/fbjs-scripts-0.8.3.tgz#b854de7a11e62a37f72dab9aaf4d9b53c4a03174" + dependencies: + ansi-colors "^1.0.1" + babel-core "^6.7.2" + babel-preset-fbjs "^2.1.2" + core-js "^2.4.1" + cross-spawn "^5.1.0" + fancy-log "^1.3.2" + object-assign "^4.0.1" + plugin-error "^0.1.2" + semver "^5.1.0" + through2 "^2.0.0" + +fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9: + version "0.8.17" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.0.tgz#965a52d9e8d05d2b857548541fb89b53a2497d9b" + dependencies: + debug "~2.2.0" + escape-html "1.0.2" + on-finished "~2.3.0" + unpipe "~1.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +function-bind@^1.1.0, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +function.prototype.name@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + is-callable "^1.1.3" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + +gauge@~1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" + dependencies: + ansi "^0.3.0" + has-unicode "^2.0.0" + lodash.pad "^4.1.0" + lodash.padend "^4.1.0" + lodash.padstart "^4.1.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +globals@^11.1.0, globals@^11.7.0: + version "11.7.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + dependencies: + function-bind "^1.1.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +hoist-non-react-statics@^2.2.0, hoist-non-react-statics@^2.2.1, hoist-non-react-statics@^2.2.2, hoist-non-react-statics@^2.3.1: + version "2.5.5" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +htmlparser2@^3.9.1: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +http-errors@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" + dependencies: + inherits "~2.0.1" + statuses "1" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" + +iconv-lite@0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" + +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +ignore@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.2.tgz#0a8dd228947ec78c2d7f736b1642a9f7317c1905" + +image-size@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +inquirer@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.1.0" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^5.5.2" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-boolean-object@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" + +is-buffer@^1.1.5, is-buffer@~1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-number-object@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-string@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" + +is-subset@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jest-docblock@^21, jest-docblock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + +jest-haste-map@^21: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" + dependencies: + fb-watchman "^2.0.0" + graceful-fs "^4.1.11" + jest-docblock "^21.2.0" + micromatch "^2.3.11" + sane "^2.0.0" + worker-farm "^1.3.1" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + +js-yaml@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jsx-ast-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" + dependencies: + array-includes "^3.0.3" + +keymirror@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35" + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +left-pad@^1.1.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash-es@^4.2.0, lodash-es@^4.2.1: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.10.tgz#62cd7104cdf5dd87f235a837f0ede0e8e5117e05" + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + +lodash.isequal@^4.1.4: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + +lodash.pad@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" + +lodash.padend@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + +lodash.padstart@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + +lodash@4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@^3.5.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^4.0.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +macos-release@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-1.1.0.tgz#831945e29365b470aa8724b0ab36c8f8959d10fb" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + +md5@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.1.0.tgz#22ec92f33ac97a6ef4dc16c0f57fa46c01ed13bb" + dependencies: + charenc "~0.0.1" + crypt "~0.0.1" + is-buffer "~1.1.1" + +md5@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" + dependencies: + charenc "~0.0.1" + crypt "~0.0.1" + is-buffer "~1.1.1" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + dependencies: + readable-stream "^2.0.1" + +merge@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" + +method-override@~2.3.5: + version "2.3.10" + resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.10.tgz#e3daf8d5dee10dd2dce7d4ae88d62bbee77476b4" + dependencies: + debug "2.6.9" + methods "~1.1.2" + parseurl "~1.3.2" + vary "~1.1.2" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +metro-bundler@^0.20.0: + version "0.20.3" + resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.3.tgz#0ded01b64e8963117017b106f75b83cfc34f3656" + dependencies: + absolute-path "^0.0.0" + async "^2.4.0" + babel-core "^6.24.1" + babel-generator "^6.24.1" + babel-plugin-external-helpers "^6.18.0" + babel-preset-es2015-node "^6.1.1" + babel-preset-fbjs "^2.1.4" + babel-preset-react-native "^4.0.0" + babel-register "^6.24.1" + babylon "^6.18.0" + chalk "^1.1.1" + concat-stream "^1.6.0" + core-js "^2.2.2" + debug "^2.2.0" + denodeify "^1.2.1" + fbjs "^0.8.14" + graceful-fs "^4.1.3" + image-size "^0.6.0" + jest-docblock "^21" + jest-haste-map "^21" + json-stable-stringify "^1.0.1" + json5 "^0.4.0" + left-pad "^1.1.3" + lodash "^4.16.6" + merge-stream "^1.0.1" + mime-types "2.1.11" + mkdirp "^0.5.1" + request "^2.79.0" + rimraf "^2.5.4" + source-map "^0.5.6" + temp "0.8.3" + throat "^4.1.0" + uglify-es "^3.1.8" + wordwrap "^1.0.0" + write-file-atomic "^1.2.0" + xpipe "^1.0.5" + +micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +"mime-db@>= 1.34.0 < 2", mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-db@~1.23.0: + version "1.23.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659" + +mime-types@2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c" + dependencies: + mime-db "~1.23.0" + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.6, mime-types@~2.1.9: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +mime@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + dependencies: + dom-walk "^0.1.0" + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.1, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +moment@2.19.3: + version "2.19.3" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.3.tgz#bdb99d270d6d7fda78cc0fbace855e27fe7da69f" + +moment@^2.19.0: + version "2.22.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" + +moo@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" + +morgan@~1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" + dependencies: + basic-auth "~1.0.3" + debug "~2.2.0" + depd "~1.0.1" + on-finished "~2.3.0" + on-headers "~1.0.0" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +multiparty@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/multiparty/-/multiparty-3.3.2.tgz#35de6804dc19643e5249f3d3e3bdc6c8ce301d3f" + dependencies: + readable-stream "~1.1.9" + stream-counter "~0.2.0" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +nearley@^2.7.10: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.15.0.tgz#d1ff5406a58064615fe6eafb429cf06fbb1b7eab" + dependencies: + moo "^0.4.3" + nomnom "~1.6.2" + railroad-diagrams "^1.0.0" + randexp "0.4.6" + semver "^5.4.1" + +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + +nice-try@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" + +node-fetch@^1.0.1, node-fetch@^1.3.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + +node-notifier@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" + dependencies: + growly "^1.3.0" + semver "^5.4.1" + shellwords "^0.1.1" + which "^1.3.0" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nomnom@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971" + dependencies: + colors "0.5.x" + underscore "~1.4.4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1, normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npmlog@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" + dependencies: + ansi "~0.3.1" + are-we-there-yet "~1.1.2" + gauge "~1.2.5" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + +object-is@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" + +object-keys@^1.0.11, object-keys@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.entries@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +object.values@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.0, on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opn@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" + dependencies: + object-assign "^4.0.1" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-2.0.1.tgz#b9a386361c17ae3a21736ef0599405c9a8c5dc5e" + dependencies: + macos-release "^1.0.0" + win-release "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + dependencies: + "@types/node" "*" + +parseurl@~1.3.0, parseurl@~1.3.1, parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + +pause@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" + +pegjs@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +plist@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/plist/-/plist-2.0.1.tgz#0a32ca9481b1c364e92e18dc55c876de9d01da8b" + dependencies: + base64-js "1.1.2" + xmlbuilder "8.2.2" + xmldom "0.1.x" + +plist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/plist/-/plist-1.2.0.tgz#084b5093ddc92506e259f874b8d9b1afb8c79593" + dependencies: + base64-js "0.0.8" + util-deprecate "1.0.2" + xmlbuilder "4.0.0" + xmldom "0.1.x" + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-format@^4.2.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-4.3.1.tgz#530be5c42b3c05b36414a7a2a4337aa80acd0e8d" + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@15.5.10: + version "15.5.10" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + dependencies: + loose-envify "^1.3.1" + object-assign "^4.1.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + +qs@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +raf@^3.2.0, raf@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" + dependencies: + performance-now "^2.1.0" + +railroad-diagrams@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" + +randexp@0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" + dependencies: + discontinuous-range "1.0.0" + ret "~0.1.10" + +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + +randomatic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +range-parser@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" + +raw-body@~2.1.2: + version "2.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" + dependencies: + bytes "2.4.0" + iconv-lite "0.4.13" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-addons-create-fragment@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" + dependencies: + fbjs "^0.8.4" + loose-envify "^1.3.1" + object-assign "^4.1.0" + +react-addons-perf@^15.4.0: + version "15.4.2" + resolved "https://registry.yarnpkg.com/react-addons-perf/-/react-addons-perf-15.4.2.tgz#110bdcf5c459c4f77cb85ed634bcd3397536383b" + dependencies: + fbjs "^0.8.4" + object-assign "^4.1.0" + +react-addons-pure-render-mixin@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-addons-pure-render-mixin/-/react-addons-pure-render-mixin-15.6.2.tgz#6b83f40b6b36ee40735cbd6125eb3f13ce1cddc9" + dependencies: + fbjs "^0.8.4" + object-assign "^4.1.0" + +react-addons-test-utils@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156" + +react-addons-update@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-addons-update/-/react-addons-update-15.6.2.tgz#e53753c5b34887974510c882d7fb075851d5e504" + dependencies: + fbjs "^0.8.9" + object-assign "^4.1.0" + +react-clone-referenced-element@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" + +react-deep-force-update@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c" + +react-devtools-core@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-2.5.2.tgz#f97bec5afae5d9318d16778065e0c214c4d5714c" + dependencies: + shell-quote "^1.6.1" + ws "^2.0.3" + +react-dom@^15.4.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.1.0" + object-assign "^4.1.0" + prop-types "^15.5.10" + +react-native-checkbox@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-native-checkbox/-/react-native-checkbox-2.0.0.tgz#453bbfd2e055a21e69ebe7842414a055d50ff449" + dependencies: + prop-types "^15.5.10" + +react-native-communications@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-native-communications/-/react-native-communications-2.2.1.tgz#7883b56b20a002eeb790c113f8616ea8692ca795" + +react-native-dismiss-keyboard@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz#32886242b3f2317e121f3aeb9b0a585e2b879b49" + +react-native-drawer-layout-polyfill@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/react-native-drawer-layout-polyfill/-/react-native-drawer-layout-polyfill-1.3.2.tgz#192c84d7a5a6b8a6d2be2c7daa5e4164518d0cc7" + dependencies: + react-native-drawer-layout "1.3.2" + +react-native-drawer-layout@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz#b9740d7663a1dc4f88a61b9c6d93d2d948ea426e" + dependencies: + react-native-dismiss-keyboard "1.0.0" + +react-native-gifted-chat@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/react-native-gifted-chat/-/react-native-gifted-chat-0.3.0.tgz#ab371723e3ddad07385d0ff1dbfcae156151daad" + dependencies: + "@expo/react-native-action-sheet" "^1.0.1" + md5 "2.2.1" + moment "^2.19.0" + prop-types "15.5.10" + react-native-communications "2.2.1" + react-native-invertible-scroll-view "^1.1.0" + react-native-lightbox "^0.7.0" + react-native-parsed-text "^0.0.19" + shallowequal "1.0.2" + uuid "3.1.0" + +react-native-image-crop-picker@0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.20.0.tgz#29b8df35eb17ff7ad61524ec09832f49e552427d" + +react-native-invertible-scroll-view@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-native-invertible-scroll-view/-/react-native-invertible-scroll-view-1.1.1.tgz#43039037e6537dc8c4f29baae1cd1a223bc25d81" + dependencies: + create-react-class "^15.6.0" + prop-types "^15.5.10" + react-clone-referenced-element "^1.0.1" + react-native-scrollable-mixin "^1.0.1" + +react-native-iphone-x-helper@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.0.2.tgz#7dbca530930f7c1ce8633cc8fd13ba94102992e1" + +react-native-iphone-x-helper@^1.0.1, react-native-iphone-x-helper@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.0.3.tgz#7a2f1e0574e899a0f1d426e6167fd98990083214" + +react-native-keyboard-aware-scroll-view@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.4.1.tgz#bda86cbe3cdf60c572a95e7e0fbac635bc9ce66d" + dependencies: + prop-types "^15.6.0" + react-native-iphone-x-helper "^1.0.1" + +react-native-lightbox@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/react-native-lightbox/-/react-native-lightbox-0.7.0.tgz#e52b4d7fcc141f59d7b23f0180de535e35b20ec9" + dependencies: + prop-types "^15.5.10" + +react-native-message-bar@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/react-native-message-bar/-/react-native-message-bar-1.6.0.tgz#79623e89655475216927090771b0238616b6f1c7" + +react-native-mock@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/react-native-mock/-/react-native-mock-0.3.1.tgz#13d22433c5351a8a7fb8aedd7862b614d087851c" + dependencies: + cubic-bezier "^0.1.2" + invariant "^2.2.1" + keymirror "^0.1.1" + raf "^3.2.0" + react-addons-create-fragment "^15.4.0" + react-addons-perf "^15.4.0" + react-addons-pure-render-mixin "^15.4.0" + react-addons-test-utils "^15.4.0" + react-addons-update "^15.4.0" + react-dom "^15.4.0" + react-timer-mixin "^0.13.3" + warning "^2.1.0" + +react-native-parsed-text@^0.0.19: + version "0.0.19" + resolved "https://registry.yarnpkg.com/react-native-parsed-text/-/react-native-parsed-text-0.0.19.tgz#1aacca6f9ee82f939f60ef985df90c97bd55c45a" + dependencies: + prop-types "^15.5.10" + +react-native-safari-view@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-native-safari-view/-/react-native-safari-view-2.1.0.tgz#1e0cd12c62bce79bc1759c7e281646b08b61c959" + +react-native-safe-area-view@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.6.0.tgz#ce01eb27905a77780219537e0f53fe9c783a8b3d" + dependencies: + hoist-non-react-statics "^2.3.1" + +react-native-scrollable-mixin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/react-native-scrollable-mixin/-/react-native-scrollable-mixin-1.0.1.tgz#34a32167b64248594154fd0d6a8b03f22740548e" + +react-native-scrollable-tab-view@0.8.0, react-native-scrollable-tab-view@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/react-native-scrollable-tab-view/-/react-native-scrollable-tab-view-0.8.0.tgz#5cb1fcfce07bf530a3c81ab51fc5071144edac5c" + dependencies: + create-react-class "^15.6.2" + prop-types "^15.6.0" + react-timer-mixin "^0.13.3" + +react-native-search-bar@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/react-native-search-bar/-/react-native-search-bar-3.1.0.tgz#48e8cc81e9947e60526cdb1cc2254451c6e598c9" + dependencies: + prop-types "^15.5.10" + +react-native-smart-emoji-picker@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/react-native-smart-emoji-picker/-/react-native-smart-emoji-picker-0.1.0.tgz#498183ed1322e943ff8e865ea9ca0790d835b0f4" + dependencies: + react-native-scrollable-tab-view "^0.8.0" + +react-native-smart-timer-enhance@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-native-smart-timer-enhance/-/react-native-smart-timer-enhance-1.0.3.tgz#47ddc19be5a6c19184449039495f25546bcd94fe" + +react-native-sticky-keyboard-accessory@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/react-native-sticky-keyboard-accessory/-/react-native-sticky-keyboard-accessory-0.1.1.tgz#176c29932a7e929b6af142c2d5651e6b9ceb547e" + dependencies: + react-native-iphone-x-helper "^1.0.2" + +react-native-tab-view@^0.0.74: + version "0.0.74" + resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.74.tgz#62c0c882d9232b461ce181d440d683b4f99d1bd8" + dependencies: + prop-types "^15.6.0" + +react-native-vector-icons@4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.4.3.tgz#9e847b8c432a17e5e0ffd60ccf09f3112a18b9df" + dependencies: + lodash "^4.0.0" + prop-types "^15.5.10" + yargs "^8.0.2" + +react-native@0.51.0: + version "0.51.0" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.51.0.tgz#fe25934b3030fd323f3ca1a70f034133465955ed" + dependencies: + absolute-path "^0.0.0" + art "^0.10.0" + babel-core "^6.24.1" + babel-plugin-syntax-trailing-function-commas "^6.20.0" + babel-plugin-transform-async-to-generator "6.16.0" + babel-plugin-transform-class-properties "^6.18.0" + babel-plugin-transform-exponentiation-operator "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.21.0" + babel-plugin-transform-object-rest-spread "^6.20.2" + babel-register "^6.24.1" + babel-runtime "^6.23.0" + base64-js "^1.1.2" + chalk "^1.1.1" + commander "^2.9.0" + connect "^2.8.3" + create-react-class "^15.5.2" + debug "^2.2.0" + denodeify "^1.2.1" + envinfo "^3.0.0" + event-target-shim "^1.0.5" + fbjs "^0.8.14" + fbjs-scripts "^0.8.1" + fs-extra "^1.0.0" + glob "^7.1.1" + graceful-fs "^4.1.3" + inquirer "^3.0.6" + lodash "^4.16.6" + metro-bundler "^0.20.0" + mime "^1.3.4" + minimist "^1.2.0" + mkdirp "^0.5.1" + node-fetch "^1.3.3" + node-notifier "^5.1.2" + npmlog "^2.0.4" + opn "^3.0.2" + optimist "^0.6.1" + plist "^1.2.0" + pretty-format "^4.2.1" + promise "^7.1.1" + prop-types "^15.5.8" + react-clone-referenced-element "^1.0.1" + react-devtools-core "^2.5.0" + react-timer-mixin "^0.13.2" + regenerator-runtime "^0.11.0" + rimraf "^2.5.4" + semver "^5.0.3" + shell-quote "1.6.1" + stacktrace-parser "^0.1.3" + whatwg-fetch "^1.0.0" + ws "^1.1.0" + xcode "^0.9.1" + xmldoc "^0.4.0" + yargs "^9.0.0" + +react-navigation@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-1.0.3.tgz#1687ea67a72a382633b01e7afda88582ebc3b5f9" + dependencies: + clamp "^1.0.1" + hoist-non-react-statics "^2.2.0" + path-to-regexp "^1.7.0" + prop-types "^15.5.10" + react-native-drawer-layout-polyfill "^1.3.2" + react-native-safe-area-view "^0.6.0" + react-native-tab-view "^0.0.74" + +react-proxy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a" + dependencies: + lodash "^4.6.1" + react-deep-force-update "^1.0.0" + +react-redux@5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946" + dependencies: + hoist-non-react-statics "^2.2.1" + invariant "^2.0.0" + lodash "^4.2.0" + lodash-es "^4.2.0" + loose-envify "^1.1.0" + prop-types "^15.5.10" + +react-timer-mixin@^0.13.2, react-timer-mixin@^0.13.3: + version "0.13.4" + resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" + +react-transform-hmr@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz#e1a40bd0aaefc72e8dfd7a7cda09af85066397bb" + dependencies: + global "^4.3.0" + react-proxy "^1.1.7" + +react@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.1.8, readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +reduce-reducers@^0.1.0: + version "0.1.5" + resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.1.5.tgz#ff77ca8068ff41007319b8b4b91533c7e0e54576" + +redux-actions@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-1.2.1.tgz#649711d88f49f1dde5bc5a1cea8ceec5b54d9181" + dependencies: + invariant "^2.2.1" + lodash "^4.13.1" + reduce-reducers "^0.1.0" + +redux-saga@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.12.0.tgz#4b6145e6f8c33a6082f7d18f30ab5d2901e621e8" + +redux@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-3.3.1.tgz#716df8004786deaf01c93ae396c84fc1041e424b" + dependencies: + lodash "^4.2.1" + lodash-es "^4.2.1" + loose-envify "^1.1.0" + +regenerate@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" + dependencies: + define-properties "^1.1.2" + +regexpp@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@^2.79.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +response-time@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" + dependencies: + depd "~1.1.0" + on-headers "~1.0.1" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + +rndm@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" + +rst-selector-parser@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" + dependencies: + lodash.flattendeep "^4.4.0" + nearley "^2.7.10" + +rsvp@^3.3.3: + version "3.6.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +rxjs@^5.5.2: + version "5.5.11" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" + dependencies: + symbol-observable "1.0.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-buffer@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +sane@^2.0.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" + dependencies: + anymatch "^2.0.0" + capture-exit "^1.2.0" + exec-sh "^0.2.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + watch "~0.18.0" + optionalDependencies: + fsevents "^1.2.3" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +sax@~1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" + +"semver@2 || 3 || 4 || 5", semver@5.x, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +send@0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.3.1" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.0.3" + statuses "~1.2.1" + +serve-favicon@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" + dependencies: + etag "~1.7.0" + fresh "0.3.0" + ms "0.7.2" + parseurl "~1.3.1" + +serve-index@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.7.3.tgz#7a057fc6ee28dc63f64566e5fa57b111a86aecd2" + dependencies: + accepts "~1.2.13" + batch "0.5.3" + debug "~2.2.0" + escape-html "~1.0.3" + http-errors "~1.3.1" + mime-types "~2.1.9" + parseurl "~1.3.1" + +serve-static@~1.10.0: + version "1.10.3" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" + dependencies: + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.13.2" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +shallowequal@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shell-quote@1.6.1, shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-plist@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-0.2.1.tgz#71766db352326928cf3a807242ba762322636723" + dependencies: + bplist-creator "0.0.7" + bplist-parser "0.1.1" + plist "2.0.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stacktrace-parser@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz#01397922e5f62ecf30845522c95c4fe1d25e7d4e" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" + +stream-buffers@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" + +stream-counter@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-0.2.0.tgz#ded266556319c8b0e222812b9cf3b26fa7d947de" + dependencies: + readable-stream "~1.1.8" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string.prototype.matchall@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz#2af8fe3d2d6dc53ca2a59bd376b089c3c152b3c8" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.10.0" + function-bind "^1.1.1" + has-symbols "^1.0.0" + regexp.prototype.flags "^1.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@5.4.0, supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + +table@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" + dependencies: + ajv "^6.0.1" + ajv-keywords "^3.0.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +tar@^4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +temp@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +throat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tsscmp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@^4.0.0: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + +type-is@~1.6.6: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +ua-parser-js@^0.7.18: + version "0.7.18" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" + +uglify-es@^3.1.8: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + +uid-safe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" + dependencies: + random-bytes "~1.0.0" + +uid-safe@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" + dependencies: + base64-url "1.2.1" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + +underscore@~1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + +util-deprecate@1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +uuid@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +uuid@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vhost@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" + +walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + dependencies: + makeerror "1.0.x" + +warning@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901" + dependencies: + loose-envify "^1.0.0" + +watch@~0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" + dependencies: + exec-sh "^0.2.0" + minimist "^1.2.0" + +whatwg-fetch@>=0.10.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + +whatwg-fetch@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@^1.2.14, which@^1.2.9, which@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +win-release@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209" + dependencies: + semver "^5.0.1" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +worker-farm@^1.3.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^1.2.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +ws@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +ws@^2.0.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" + dependencies: + safe-buffer "~5.0.1" + ultron "~1.1.0" + +xcode@^0.9.1: + version "0.9.3" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-0.9.3.tgz#910a89c16aee6cc0b42ca805a6d0b4cf87211cf3" + dependencies: + pegjs "^0.10.0" + simple-plist "^0.2.1" + uuid "3.0.1" + +xmlbuilder@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.0.0.tgz#98b8f651ca30aa624036f127d11cc66dc7b907a3" + dependencies: + lodash "^3.5.0" + +xmlbuilder@8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" + +xmldoc@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-0.4.0.tgz#d257224be8393eaacbf837ef227fd8ec25b36888" + dependencies: + sax "~1.1.1" + +xmldom@0.1.x: + version "0.1.27" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" + +xpipe@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf" + +xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + +yargs@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" From b9170cba12b1fc69f94532882ed69e79bb4ea401 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 5 Aug 2018 19:56:24 +0800 Subject: [PATCH 02/58] refactor: move style next to component; import absolute path --- index.js | 2 +- .../styles/HeaderRightButton.style.js} | 2 +- .../styles/Indicator.style.js} | 0 .../styles/KeyboardAccessory.style.js} | 1 - .../_List.js => common/styles/List.style.js} | 2 +- .../_Main.js => common/styles/Main.style.js} | 2 +- .../styles/Modal.style.js} | 1 - .../styles/ScrollableTabView.style.js} | 2 +- .../styles/colors.style.js} | 0 .../GiftedChatLoadEarlierButton.js | 0 .../components}/GiftedChatMessageText.js | 3 +- .../components}/GiftedChatSendButton.js | 0 .../components}/LoadingSpinnerOverlay.js | 0 .../vendor/components}/MessageTabBar.js | 3 +- src/components/3rd_party/EmojiDotTabBar.js | 58 -------------- src/components/3rd_party/EmojiTabBar.js | 58 -------------- src/components/{ => AlertCount}/AlertCount.js | 2 +- .../AlertCount/AlertCount.style.js} | 2 +- src/components/{ => Avatar}/Avatar.js | 2 +- .../Avatar/Avatar.style.js} | 1 - src/components/{ => Comment}/Comment.js | 13 ++-- .../Comment/Comment.style.js} | 2 +- src/components/{ => Content}/Content.js | 12 +-- .../Content/Content.style.js} | 3 +- src/components/{ => ForumItem}/ForumItem.js | 5 +- .../ForumItem/ForumItem.style.js} | 2 +- src/components/{ => ForumItems}/ForumItems.js | 2 +- .../ForumListModal.js | 11 +-- src/components/{ => FriendItem}/FriendItem.js | 9 ++- .../FriendItem/FriendItem.style.js} | 2 +- src/components/{ => FriendList}/FriendList.js | 7 +- .../FriendList/FriendList.style.js} | 0 .../FriendListModal.js | 11 +-- src/components/{ => Header}/Header.js | 5 +- .../Header/Header.style.js} | 2 +- .../{ => ImagePreview}/ImagePreview.js | 3 +- .../ImagePreview/ImagePreview.style.js} | 0 .../{ => ImageUploader}/ImageUploader.js | 11 +-- .../ImageUploader/ImageUploader.style.js} | 2 +- .../{ => LoadingSpinner}/LoadingSpinner.js | 9 ++- .../LoadingSpinner/LoadingSpinner.style.js} | 2 +- .../{modal => LoginModal}/LoginModal.js | 21 ++--- .../LoginModal/LoginModal.style.js} | 2 +- .../{ => MenuBottomItem}/MenuBottomItem.js | 5 +- .../MenuBottomItem/MenuBottomItem.style.js} | 2 +- .../{button => MenuButton}/MenuButton.js | 5 +- .../MenuButton/MenuButton.style.js} | 2 +- src/components/{ => MenuItem}/MenuItem.js | 7 +- .../MenuItem/MenuItem.style.js} | 2 +- .../{ => MenuProfile}/MenuProfile.js | 5 +- .../MenuProfile/MenuProfile.style.js} | 2 +- src/components/{ => NotifyItem}/NotifyItem.js | 7 +- .../NotifyItem/NotifyItem.style.js} | 2 +- src/components/{ => NotifyList}/NotifyList.js | 9 ++- .../NotifySystemItem.js | 5 +- src/components/{ => Picker}/Picker.js | 7 +- .../Picker/Picker.style.js} | 2 +- .../{ => PmSessionItem}/PmSessionItem.js | 7 +- .../PmSessionItem/PmSessionItem.style.js} | 2 +- .../{ => PmSessionList}/PmSessionList.js | 7 +- .../{button => PopButton}/PopButton.js | 0 .../{ => ProgressImage}/ProgressImage.js | 11 +-- .../ProgressImage/ProgressImage.style.js} | 2 +- .../PublishButton.js | 3 +- .../{modal => PublishModal}/PublishModal.js | 34 ++++----- .../PublishModal/PublishModal.style.js} | 2 +- .../{modal => ReplyModal}/ReplyModal.js | 23 +++--- .../ReplyModal/ReplyModal.style.js} | 2 +- src/components/{ => RewardList}/RewardList.js | 5 +- .../RewardList/RewardList.style.js} | 2 +- .../{ => SettingItem}/SettingItem.js | 5 +- .../SettingItem/SettingItem.style.js} | 2 +- .../SettingSwitchItem.js | 5 +- .../SettingSwitchItem.style.js} | 2 +- .../{ => SubForumItem}/SubForumItem.js | 9 ++- .../SubForumItem/SubForumItem.style.js} | 2 +- .../{ => SubForumList}/SubForumList.js | 2 +- src/components/{ => TopicItem}/TopicItem.js | 9 ++- .../TopicItem/TopicItem.style.js} | 2 +- src/components/{ => TopicList}/TopicList.js | 9 ++- src/components/{ => VoteList}/VoteList.js | 3 +- .../VoteList/VoteList.style.js} | 2 +- src/components/button/index.js | 9 --- src/constants/forums.js | 76 +++++++++---------- src/containers/{ => About}/About.js | 18 ++--- .../About/About.style.js} | 2 +- src/containers/{ => App}/App.js | 6 +- .../{ => ForumDetail}/ForumDetail.js | 19 ++--- src/containers/{ => ForumList}/ForumList.js | 11 +-- src/containers/{ => Home}/Home.js | 18 +++-- src/containers/{ => Individual}/Individual.js | 21 ++--- .../Individual/Individual.style.js} | 2 +- .../{ => Information}/Information.js | 23 +++--- src/containers/{ => Menu}/Menu.js | 38 +++++----- .../Menu/Menu.style.js} | 2 +- src/containers/{ => Message}/Message.js | 25 +++--- src/containers/{ => Navigator}/Navigator.js | 47 ++++++------ src/containers/{ => PmList}/PmList.js | 19 ++--- .../PmList/PmList.style.js} | 1 - src/containers/{ => Search}/Search.js | 15 ++-- .../Search/Search.style.js} | 2 +- src/containers/{ => Settings}/Settings.js | 17 +++-- .../Settings/Settings.style.js} | 2 +- .../{ => TopicDetail}/TopicDetail.js | 43 ++++++----- .../TopicDetail/TopicDetail.style.js} | 2 +- src/containers/{ => WebPage}/WebPage.js | 0 src/package.json | 3 + src/reducers/forumList.js | 4 +- src/reducers/message/alert.js | 8 +- src/reducers/message/notifyList.js | 4 +- src/reducers/message/pmList.js | 2 +- src/reducers/message/pmSessionList.js | 4 +- src/reducers/message/send.js | 2 +- src/reducers/settings.js | 2 +- src/reducers/topic/search.js | 2 +- src/reducers/topic/topicItem.js | 2 +- src/reducers/topic/topicList.js | 4 +- src/reducers/user.js | 2 +- src/reducers/user/friendList.js | 2 +- src/reducers/user/topicList.js | 4 +- src/reducers/user/userItem.js | 2 +- src/sagas/index.js | 36 ++++----- src/services/ImagePicker.js | 2 +- src/services/api.js | 6 +- src/store/configureStore.js | 2 +- src/utils/app.js | 2 +- src/utils/contentParser.js | 4 +- src/utils/request.js | 2 +- tests/components/Content.test.js | 8 +- tests/components/TopicList.test.js | 2 +- 130 files changed, 466 insertions(+), 554 deletions(-) rename src/{styles/components/button/_HeaderRightButton.js => common/styles/HeaderRightButton.style.js} (78%) rename src/{styles/common/_Indicator.js => common/styles/Indicator.style.js} (100%) rename src/{styles/components/_KeyboardAccessory.js => common/styles/KeyboardAccessory.style.js} (87%) rename src/{styles/common/_List.js => common/styles/List.style.js} (82%) rename src/{styles/components/_Main.js => common/styles/Main.style.js} (74%) rename src/{styles/common/_Modal.js => common/styles/Modal.style.js} (88%) rename src/{styles/common/_ScrollableTabView.js => common/styles/ScrollableTabView.style.js} (79%) rename src/{styles/common/_colors.js => common/styles/colors.style.js} (100%) rename src/{components/3rd_party => common/vendor/components}/GiftedChatLoadEarlierButton.js (100%) rename src/{components/3rd_party => common/vendor/components}/GiftedChatMessageText.js (98%) rename src/{components/3rd_party => common/vendor/components}/GiftedChatSendButton.js (100%) rename src/{components/3rd_party => common/vendor/components}/LoadingSpinnerOverlay.js (100%) rename src/{components/3rd_party => common/vendor/components}/MessageTabBar.js (98%) delete mode 100644 src/components/3rd_party/EmojiDotTabBar.js delete mode 100644 src/components/3rd_party/EmojiTabBar.js rename src/components/{ => AlertCount}/AlertCount.js (89%) rename src/{styles/components/_AlertCount.js => components/AlertCount/AlertCount.style.js} (91%) rename src/components/{ => Avatar}/Avatar.js (95%) rename src/{styles/components/_Avatar.js => components/Avatar/Avatar.style.js} (79%) rename src/components/{ => Comment}/Comment.js (93%) rename src/{styles/components/_Comment.js => components/Comment/Comment.style.js} (95%) rename src/components/{ => Content}/Content.js (95%) rename src/{styles/components/_Content.js => components/Content/Content.style.js} (83%) rename src/components/{ => ForumItem}/ForumItem.js (85%) rename src/{styles/components/_ForumItem.js => components/ForumItem/ForumItem.style.js} (86%) rename src/components/{ => ForumItems}/ForumItems.js (95%) rename src/components/{modal => ForumListModal}/ForumListModal.js (83%) rename src/components/{ => FriendItem}/FriendItem.js (84%) rename src/{styles/components/_FriendItem.js => components/FriendItem/FriendItem.style.js} (91%) rename src/components/{ => FriendList}/FriendList.js (92%) rename src/{styles/components/_FriendList.js => components/FriendList/FriendList.style.js} (100%) rename src/components/{modal => FriendListModal}/FriendListModal.js (82%) rename src/components/{ => Header}/Header.js (94%) rename src/{styles/components/_Header.js => components/Header/Header.style.js} (95%) rename src/components/{ => ImagePreview}/ImagePreview.js (92%) rename src/{styles/components/_ImagePreview.js => components/ImagePreview/ImagePreview.style.js} (100%) rename src/components/{ => ImageUploader}/ImageUploader.js (91%) rename src/{styles/components/_ImageUploader.js => components/ImageUploader/ImageUploader.style.js} (93%) rename src/components/{ => LoadingSpinner}/LoadingSpinner.js (71%) rename src/{styles/components/_LoadingSpinner.js => components/LoadingSpinner/LoadingSpinner.style.js} (78%) rename src/components/{modal => LoginModal}/LoginModal.js (89%) rename src/{styles/components/modal/_LoginModal.js => components/LoginModal/LoginModal.style.js} (94%) rename src/components/{ => MenuBottomItem}/MenuBottomItem.js (90%) rename src/{styles/components/_MenuBottomItem.js => components/MenuBottomItem/MenuBottomItem.style.js} (85%) rename src/components/{button => MenuButton}/MenuButton.js (89%) rename src/{styles/components/button/_MenuButton.js => components/MenuButton/MenuButton.style.js} (82%) rename src/components/{ => MenuItem}/MenuItem.js (86%) rename src/{styles/components/_MenuItem.js => components/MenuItem/MenuItem.style.js} (91%) rename src/components/{ => MenuProfile}/MenuProfile.js (90%) rename src/{styles/components/_MenuProfile.js => components/MenuProfile/MenuProfile.style.js} (93%) rename src/components/{ => NotifyItem}/NotifyItem.js (93%) rename src/{styles/components/_NotifyItem.js => components/NotifyItem/NotifyItem.style.js} (95%) rename src/components/{ => NotifyList}/NotifyList.js (90%) rename src/components/{ => NotifySystemItem}/NotifySystemItem.js (88%) rename src/components/{ => Picker}/Picker.js (91%) rename src/{styles/components/_Picker.js => components/Picker/Picker.style.js} (86%) rename src/components/{ => PmSessionItem}/PmSessionItem.js (92%) rename src/{styles/components/_PmSessionItem.js => components/PmSessionItem/PmSessionItem.style.js} (94%) rename src/components/{ => PmSessionList}/PmSessionList.js (92%) rename src/components/{button => PopButton}/PopButton.js (100%) rename src/components/{ => ProgressImage}/ProgressImage.js (91%) rename src/{styles/components/_ProgressImage.js => components/ProgressImage/ProgressImage.style.js} (92%) rename src/components/{button => PublishButton}/PublishButton.js (81%) rename src/components/{modal => PublishModal}/PublishModal.js (94%) rename src/{styles/components/modal/_PublishModal.js => components/PublishModal/PublishModal.style.js} (93%) rename src/components/{modal => ReplyModal}/ReplyModal.js (93%) rename src/{styles/components/modal/_ReplyModal.js => components/ReplyModal/ReplyModal.style.js} (92%) rename src/components/{ => RewardList}/RewardList.js (94%) rename src/{styles/components/_RewardList.js => components/RewardList/RewardList.style.js} (92%) rename src/components/{ => SettingItem}/SettingItem.js (90%) rename src/{styles/components/_SettingItem.js => components/SettingItem/SettingItem.style.js} (93%) rename src/components/{ => SettingSwitchItem}/SettingSwitchItem.js (81%) rename src/{styles/components/_SettingSwitchItem.js => components/SettingSwitchItem/SettingSwitchItem.style.js} (75%) rename src/components/{ => SubForumItem}/SubForumItem.js (90%) rename src/{styles/components/_SubForumItem.js => components/SubForumItem/SubForumItem.style.js} (95%) rename src/components/{ => SubForumList}/SubForumList.js (87%) rename src/components/{ => TopicItem}/TopicItem.js (94%) rename src/{styles/components/_TopicItem.js => components/TopicItem/TopicItem.style.js} (96%) rename src/components/{ => TopicList}/TopicList.js (94%) rename src/components/{ => VoteList}/VoteList.js (98%) rename src/{styles/components/_VoteList.js => components/VoteList/VoteList.style.js} (96%) delete mode 100644 src/components/button/index.js rename src/containers/{ => About}/About.js (79%) rename src/{styles/containers/_About.js => containers/About/About.style.js} (91%) rename src/containers/{ => App}/App.js (67%) rename src/containers/{ => ForumDetail}/ForumDetail.js (91%) rename src/containers/{ => ForumList}/ForumList.js (82%) rename src/containers/{ => Home}/Home.js (85%) rename src/containers/{ => Individual}/Individual.js (90%) rename src/{styles/containers/_Individual.js => containers/Individual/Individual.style.js} (88%) rename src/containers/{ => Information}/Information.js (82%) rename src/containers/{ => Menu}/Menu.js (74%) rename src/{styles/containers/_Menu.js => containers/Menu/Menu.style.js} (94%) rename src/containers/{ => Message}/Message.js (85%) rename src/containers/{ => Navigator}/Navigator.js (76%) rename src/containers/{ => PmList}/PmList.js (90%) rename src/{styles/containers/_PmList.js => containers/PmList/PmList.style.js} (87%) rename src/containers/{ => Search}/Search.js (86%) rename src/{styles/containers/_Search.js => containers/Search/Search.style.js} (80%) rename src/containers/{ => Settings}/Settings.js (84%) rename src/{styles/containers/_Settings.js => containers/Settings/Settings.style.js} (88%) rename src/containers/{ => TopicDetail}/TopicDetail.js (92%) rename src/{styles/containers/_TopicDetail.js => containers/TopicDetail/TopicDetail.style.js} (97%) rename src/containers/{ => WebPage}/WebPage.js (100%) create mode 100644 src/package.json diff --git a/index.js b/index.js index a790b1c..1cab52d 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,6 @@ import 'es6-symbol/implement'; import { AppRegistry } from 'react-native'; -import App from './src/containers/App'; +import App from './src/containers/App/App'; AppRegistry.registerComponent('stuhome', () => App); diff --git a/src/styles/components/button/_HeaderRightButton.js b/src/common/styles/HeaderRightButton.style.js similarity index 78% rename from src/styles/components/button/_HeaderRightButton.js rename to src/common/styles/HeaderRightButton.style.js index 03ed2cd..e81410b 100644 --- a/src/styles/components/button/_HeaderRightButton.js +++ b/src/common/styles/HeaderRightButton.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ button: { diff --git a/src/styles/common/_Indicator.js b/src/common/styles/Indicator.style.js similarity index 100% rename from src/styles/common/_Indicator.js rename to src/common/styles/Indicator.style.js diff --git a/src/styles/components/_KeyboardAccessory.js b/src/common/styles/KeyboardAccessory.style.js similarity index 87% rename from src/styles/components/_KeyboardAccessory.js rename to src/common/styles/KeyboardAccessory.style.js index 3266dd3..1ef8e2b 100644 --- a/src/styles/components/_KeyboardAccessory.js +++ b/src/common/styles/KeyboardAccessory.style.js @@ -1,5 +1,4 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; export default StyleSheet.create({ keyboardAccessoryContainer: { diff --git a/src/styles/common/_List.js b/src/common/styles/List.style.js similarity index 82% rename from src/styles/common/_List.js rename to src/common/styles/List.style.js index f4b1af0..a4d9f74 100644 --- a/src/styles/common/_List.js +++ b/src/common/styles/List.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from './_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ emptyView: { diff --git a/src/styles/components/_Main.js b/src/common/styles/Main.style.js similarity index 74% rename from src/styles/components/_Main.js rename to src/common/styles/Main.style.js index 4c5237d..56da610 100644 --- a/src/styles/components/_Main.js +++ b/src/common/styles/Main.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/styles/common/_Modal.js b/src/common/styles/Modal.style.js similarity index 88% rename from src/styles/common/_Modal.js rename to src/common/styles/Modal.style.js index ce43927..18ef67f 100644 --- a/src/styles/common/_Modal.js +++ b/src/common/styles/Modal.style.js @@ -1,5 +1,4 @@ import { StyleSheet } from 'react-native'; -import colors from './_colors'; export default StyleSheet.create({ container: { diff --git a/src/styles/common/_ScrollableTabView.js b/src/common/styles/ScrollableTabView.style.js similarity index 79% rename from src/styles/common/_ScrollableTabView.js rename to src/common/styles/ScrollableTabView.style.js index f6005a0..8222425 100644 --- a/src/styles/common/_ScrollableTabView.js +++ b/src/common/styles/ScrollableTabView.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from './_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ tabBarUnderline: { diff --git a/src/styles/common/_colors.js b/src/common/styles/colors.style.js similarity index 100% rename from src/styles/common/_colors.js rename to src/common/styles/colors.style.js diff --git a/src/components/3rd_party/GiftedChatLoadEarlierButton.js b/src/common/vendor/components/GiftedChatLoadEarlierButton.js similarity index 100% rename from src/components/3rd_party/GiftedChatLoadEarlierButton.js rename to src/common/vendor/components/GiftedChatLoadEarlierButton.js diff --git a/src/components/3rd_party/GiftedChatMessageText.js b/src/common/vendor/components/GiftedChatMessageText.js similarity index 98% rename from src/components/3rd_party/GiftedChatMessageText.js rename to src/common/vendor/components/GiftedChatMessageText.js index 19bb4e4..f534ab8 100644 --- a/src/components/3rd_party/GiftedChatMessageText.js +++ b/src/common/vendor/components/GiftedChatMessageText.js @@ -10,10 +10,9 @@ import { View, ViewPropTypes, } from 'react-native'; -import { parseContentWithEmoji } from '../../utils/contentParser'; - import ParsedText from 'react-native-parsed-text'; import Communications from 'react-native-communications'; +import { parseContentWithEmoji } from '~/utils/contentParser'; const WWW_URL_PATTERN = /^www\./i; diff --git a/src/components/3rd_party/GiftedChatSendButton.js b/src/common/vendor/components/GiftedChatSendButton.js similarity index 100% rename from src/components/3rd_party/GiftedChatSendButton.js rename to src/common/vendor/components/GiftedChatSendButton.js diff --git a/src/components/3rd_party/LoadingSpinnerOverlay.js b/src/common/vendor/components/LoadingSpinnerOverlay.js similarity index 100% rename from src/components/3rd_party/LoadingSpinnerOverlay.js rename to src/common/vendor/components/LoadingSpinnerOverlay.js diff --git a/src/components/3rd_party/MessageTabBar.js b/src/common/vendor/components/MessageTabBar.js similarity index 98% rename from src/components/3rd_party/MessageTabBar.js rename to src/common/vendor/components/MessageTabBar.js index b853493..69087e0 100644 --- a/src/components/3rd_party/MessageTabBar.js +++ b/src/common/vendor/components/MessageTabBar.js @@ -12,7 +12,8 @@ const { Animated, TouchableOpacity } = ReactNative; -import AlertCount from '../AlertCount'; +import AlertCount from '~/components/AlertCount/AlertCount'; + const Button = (props) => { return {props.children} diff --git a/src/components/3rd_party/EmojiDotTabBar.js b/src/components/3rd_party/EmojiDotTabBar.js deleted file mode 100644 index 745c815..0000000 --- a/src/components/3rd_party/EmojiDotTabBar.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from 'react'; -import { - StyleSheet, - Text, - View, - Animated, - Image, - Dimensions, - TouchableOpacity -} from 'react-native'; - -const window = Dimensions.get('window'); - -export default class EmojiDotTabBar extends Component { - render() { - return ( - - {this.props.tabs.map((item, index) => { - return ( - this.props.goToPage(index)}> - - - ); - })} - - ); - } -} - -const styles = StyleSheet.create({ - container: { - height: 50, - width: window.width, - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center' - }, - dotWrapper: { - height: 10, - width: 10, - borderRadius: 5, - marginHorizontal: 3, - }, - dot: { - backgroundColor: '#d6d6d6', - height: 8, - width: 8, - borderRadius: 4, - marginLeft: 1, - marginTop: 1 - }, - activeDot: { - backgroundColor: '#8b8b8b', - } -}); diff --git a/src/components/3rd_party/EmojiTabBar.js b/src/components/3rd_party/EmojiTabBar.js deleted file mode 100644 index 204acde..0000000 --- a/src/components/3rd_party/EmojiTabBar.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from 'react'; -import { - StyleSheet, - Text, - View, - Animated, - Image, - TouchableOpacity, - Dimensions -} from 'react-native'; - -const window = Dimensions.get('window'); - -export default class EmojiTabBar extends Component { - render() { - return ( - - {this.props.tabs.map((image, index) => { - return ( - this.props.goToPage(index)}> - - - ); - })} - - ); - } -} - -const styles = StyleSheet.create({ - container: { - height: 50, - width: window.width, - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'white' - }, - imageWrapper: { - height: 50, - // 9 is the number of emoji groups - width: window.width / 9, - justifyContent: 'center', - }, - activeImage: { - backgroundColor: '#f6f6f6', - }, - image: { - height: 40, - width: window.width / 9, - } -}); diff --git a/src/components/AlertCount.js b/src/components/AlertCount/AlertCount.js similarity index 89% rename from src/components/AlertCount.js rename to src/components/AlertCount/AlertCount.js index d9fe602..e66161b 100644 --- a/src/components/AlertCount.js +++ b/src/components/AlertCount/AlertCount.js @@ -3,7 +3,7 @@ import { View, Text, } from 'react-native'; -import styles from '../styles/components/_AlertCount'; +import styles from './AlertCount.style'; export default class AlertCount extends Component { render() { diff --git a/src/styles/components/_AlertCount.js b/src/components/AlertCount/AlertCount.style.js similarity index 91% rename from src/styles/components/_AlertCount.js rename to src/components/AlertCount/AlertCount.style.js index b0bc05e..eb90d42 100644 --- a/src/styles/components/_AlertCount.js +++ b/src/components/AlertCount/AlertCount.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ alertCommonBackground: { diff --git a/src/components/Avatar.js b/src/components/Avatar/Avatar.js similarity index 95% rename from src/components/Avatar.js rename to src/components/Avatar/Avatar.js index f1afa3c..db49018 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar/Avatar.js @@ -4,7 +4,7 @@ import { Image, TouchableOpacity } from 'react-native'; -import styles from '../styles/components/_Avatar'; +import styles from './Avatar.style'; export default class Avatar extends Component { render() { diff --git a/src/styles/components/_Avatar.js b/src/components/Avatar/Avatar.style.js similarity index 79% rename from src/styles/components/_Avatar.js rename to src/components/Avatar/Avatar.style.js index 63c8e04..550ecca 100644 --- a/src/styles/components/_Avatar.js +++ b/src/components/Avatar/Avatar.style.js @@ -1,5 +1,4 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; export default StyleSheet.create({ avatar: { diff --git a/src/components/Comment.js b/src/components/Comment/Comment.js similarity index 93% rename from src/components/Comment.js rename to src/components/Comment/Comment.js index 337b07c..f34f667 100644 --- a/src/components/Comment.js +++ b/src/components/Comment/Comment.js @@ -6,14 +6,15 @@ import { ActionSheetIOS, Clipboard } from 'react-native'; -import Content from './Content'; import Icon from 'react-native-vector-icons/FontAwesome'; -import Avatar from './Avatar'; import moment from 'moment'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_Comment'; -import MessageBar from '../services/MessageBar'; -import SafariView from '../services/SafariView'; +import Content from '~/components/Content/Content'; +import Avatar from '~/components/Avatar/Avatar'; +import MessageBar from '~/services/MessageBar'; +import SafariView from '~/services/SafariView'; + +import colors from '~/common/styles/colors.style'; +import styles from './Comment.style'; export default class Comment extends Component { showOptions() { diff --git a/src/styles/components/_Comment.js b/src/components/Comment/Comment.style.js similarity index 95% rename from src/styles/components/_Comment.js rename to src/components/Comment/Comment.style.js index 77c911e..52c93ee 100644 --- a/src/styles/components/_Comment.js +++ b/src/components/Comment/Comment.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ commentItem: { diff --git a/src/components/Content.js b/src/components/Content/Content.js similarity index 95% rename from src/components/Content.js rename to src/components/Content/Content.js index 8686dc4..0ae933a 100644 --- a/src/components/Content.js +++ b/src/components/Content/Content.js @@ -4,12 +4,12 @@ import { Text, TouchableHighlight } from 'react-native'; -import ProgressImage from './ProgressImage'; -import styles from '../styles/components/_Content'; -import colors from '../styles/common/_colors'; -import { parseContentWithEmoji } from '../utils/contentParser'; -import { DOMAIN_ROOT } from '../config'; -import SafariView from '../services/SafariView'; +import ProgressImage from '~/components/ProgressImage/ProgressImage'; +import SafariView from '~/services/SafariView'; +import { parseContentWithEmoji } from '~/utils/contentParser'; +import { DOMAIN_ROOT } from '~/config'; + +import styles from './Content.style'; export default class Content extends Component { isSameContentType(previous, current) { diff --git a/src/styles/components/_Content.js b/src/components/Content/Content.style.js similarity index 83% rename from src/styles/components/_Content.js rename to src/components/Content/Content.style.js index 4e10c4d..57f632b 100644 --- a/src/styles/components/_Content.js +++ b/src/components/Content/Content.style.js @@ -1,7 +1,6 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; import Dimensions from 'Dimensions'; -import imageStyles from './_ProgressImage'; +import colors from '~/common/styles/colors.style'; const window = Dimensions.get('window'); diff --git a/src/components/ForumItem.js b/src/components/ForumItem/ForumItem.js similarity index 85% rename from src/components/ForumItem.js rename to src/components/ForumItem/ForumItem.js index d6db4b3..bc7a42e 100644 --- a/src/components/ForumItem.js +++ b/src/components/ForumItem/ForumItem.js @@ -3,8 +3,9 @@ import { View, Text } from 'react-native'; -import styles from '../styles/components/_ForumItem'; -import SubForumList from './SubForumList'; +import SubForumList from '~/components/SubForumList/SubForumList'; + +import styles from './ForumItem.style'; export default class ForumItem extends Component { render() { diff --git a/src/styles/components/_ForumItem.js b/src/components/ForumItem/ForumItem.style.js similarity index 86% rename from src/styles/components/_ForumItem.js rename to src/components/ForumItem/ForumItem.style.js index e4e4e8e..86d249b 100644 --- a/src/styles/components/_ForumItem.js +++ b/src/components/ForumItem/ForumItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/ForumItems.js b/src/components/ForumItems/ForumItems.js similarity index 95% rename from src/components/ForumItems.js rename to src/components/ForumItems/ForumItems.js index dd8e065..42ef554 100644 --- a/src/components/ForumItems.js +++ b/src/components/ForumItems/ForumItems.js @@ -3,7 +3,7 @@ import { FlatList, RefreshControl } from 'react-native'; -import ForumItem from '../components/ForumItem'; +import ForumItem from '~/components/ForumItem/ForumItem'; export default class ForumItems extends Component { componentDidMount() { diff --git a/src/components/modal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js similarity index 83% rename from src/components/modal/ForumListModal.js rename to src/components/ForumListModal/ForumListModal.js index 94059c2..defdbc8 100644 --- a/src/components/modal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -5,11 +5,12 @@ import { } from 'react-native'; import { connect } from 'react-redux'; import _ from 'lodash'; -import ForumItems from '../ForumItems'; -import mainStyles from '../../styles/components/_Main'; -import modalStyles from '../../styles/common/_Modal'; -import Header from '../Header'; -import { invalidateForumList, fetchForumList } from '../../actions/forumAction'; +import ForumItems from '~/components/ForumItems/ForumItems'; +import Header from '~/components/Header/Header'; +import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; + +import mainStyles from '~/common/styles/Main.style'; +import modalStyles from '~/common/styles/Modal.style'; class ForumListModal extends Component { constructor(props) { diff --git a/src/components/FriendItem.js b/src/components/FriendItem/FriendItem.js similarity index 84% rename from src/components/FriendItem.js rename to src/components/FriendItem/FriendItem.js index 55b6766..38b3941 100644 --- a/src/components/FriendItem.js +++ b/src/components/FriendItem/FriendItem.js @@ -5,10 +5,11 @@ import { TouchableHighlight } from 'react-native'; import moment from 'moment'; -import Avatar from './Avatar'; -import { AVATAR_ROOT } from '../config'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_FriendItem'; +import Avatar from '~/components/Avatar/Avatar'; +import { AVATAR_ROOT } from '~/config'; + +import colors from '~/common/styles/colors.style'; +import styles from './FriendItem.style'; export default class FriendItem extends Component { render() { diff --git a/src/styles/components/_FriendItem.js b/src/components/FriendItem/FriendItem.style.js similarity index 91% rename from src/styles/components/_FriendItem.js rename to src/components/FriendItem/FriendItem.style.js index 3309c56..edc71e7 100644 --- a/src/styles/components/_FriendItem.js +++ b/src/components/FriendItem/FriendItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/FriendList.js b/src/components/FriendList/FriendList.js similarity index 92% rename from src/components/FriendList.js rename to src/components/FriendList/FriendList.js index 3908ac9..94a268e 100644 --- a/src/components/FriendList.js +++ b/src/components/FriendList/FriendList.js @@ -6,9 +6,10 @@ import { RefreshControl, ActivityIndicator } from 'react-native'; -import listStyles from '../styles/common/_List'; -import indicatorStyles from '../styles/common/_Indicator'; -import FriendItem from './FriendItem'; +import FriendItem from '~/components/FriendItem/FriendItem'; + +import listStyles from '~/common/styles/List.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; export default class FriendList extends Component { endReached() { diff --git a/src/styles/components/_FriendList.js b/src/components/FriendList/FriendList.style.js similarity index 100% rename from src/styles/components/_FriendList.js rename to src/components/FriendList/FriendList.style.js diff --git a/src/components/modal/FriendListModal.js b/src/components/FriendListModal/FriendListModal.js similarity index 82% rename from src/components/modal/FriendListModal.js rename to src/components/FriendListModal/FriendListModal.js index 6727b05..6127716 100644 --- a/src/components/modal/FriendListModal.js +++ b/src/components/FriendListModal/FriendListModal.js @@ -5,11 +5,12 @@ import { } from 'react-native'; import { connect } from 'react-redux'; import _ from 'lodash'; -import FriendList from '../FriendList'; -import mainStyles from '../../styles/components/_Main'; -import modalStyles from '../../styles/common/_Modal'; -import Header from '../Header'; -import { invalidateFriendList, fetchFriendList } from '../../actions/user/friendListAction'; +import FriendList from '~/components/FriendList/FriendList'; +import Header from '~/components/Header/Header'; +import { invalidateFriendList, fetchFriendList } from '~/actions/user/friendListAction'; + +import mainStyles from '~/common/styles/Main.style'; +import modalStyles from '~/common/styles/Modal.style'; class FriendListModal extends Component { constructor(props) { diff --git a/src/components/Header.js b/src/components/Header/Header.js similarity index 94% rename from src/components/Header.js rename to src/components/Header/Header.js index f1be634..25bb760 100644 --- a/src/components/Header.js +++ b/src/components/Header/Header.js @@ -4,8 +4,9 @@ import { Text } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -import styles from '../styles/components/_Header'; -import { MenuButton } from './button'; +import MenuButton from '~/components/MenuButton/MenuButton'; + +import styles from './Header.style'; export default class Header extends Component { render() { diff --git a/src/styles/components/_Header.js b/src/components/Header/Header.style.js similarity index 95% rename from src/styles/components/_Header.js rename to src/components/Header/Header.style.js index 8d93005..0573cc3 100644 --- a/src/styles/components/_Header.js +++ b/src/components/Header/Header.style.js @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native'; import { ifIphoneX } from 'react-native-iphone-x-helper'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/ImagePreview.js b/src/components/ImagePreview/ImagePreview.js similarity index 92% rename from src/components/ImagePreview.js rename to src/components/ImagePreview/ImagePreview.js index be86759..4c4d05f 100644 --- a/src/components/ImagePreview.js +++ b/src/components/ImagePreview/ImagePreview.js @@ -5,7 +5,8 @@ import { Image, TouchableWithoutFeedback } from 'react-native'; -import styles from '../styles/components/_ImagePreview'; + +import styles from './ImagePreview.style'; export default class ImagePreview extends Component { render() { diff --git a/src/styles/components/_ImagePreview.js b/src/components/ImagePreview/ImagePreview.style.js similarity index 100% rename from src/styles/components/_ImagePreview.js rename to src/components/ImagePreview/ImagePreview.style.js diff --git a/src/components/ImageUploader.js b/src/components/ImageUploader/ImageUploader.js similarity index 91% rename from src/components/ImageUploader.js rename to src/components/ImageUploader/ImageUploader.js index 7c2c684..c744d0a 100644 --- a/src/components/ImageUploader.js +++ b/src/components/ImageUploader/ImageUploader.js @@ -4,12 +4,13 @@ import { Image, TouchableHighlight } from 'react-native'; -import ImagePicker from '../services/ImagePicker'; -import ImagePreview from './ImagePreview'; import Icon from 'react-native-vector-icons/FontAwesome'; -import styles from '../styles/components/_ImageUploader'; -import colors from '../styles/common/_colors'; -import { MAX_UPLOAD_IMAGES_COUNT } from '../config'; +import ImagePreview from '~/components/ImagePreview/ImagePreview'; +import ImagePicker from '~/services/ImagePicker'; +import { MAX_UPLOAD_IMAGES_COUNT } from '~/config'; + +import colors from '~/common/styles/colors.style'; +import styles from './ImageUploader.style'; export default class ImageUploader extends Component { constructor(props) { diff --git a/src/styles/components/_ImageUploader.js b/src/components/ImageUploader/ImageUploader.style.js similarity index 93% rename from src/styles/components/_ImageUploader.js rename to src/components/ImageUploader/ImageUploader.style.js index 35e51b5..bd0cfa4 100644 --- a/src/styles/components/_ImageUploader.js +++ b/src/components/ImageUploader/ImageUploader.style.js @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native'; import Dimensions from 'Dimensions'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; const window = Dimensions.get('window'); const IMAGE_WIDTH = (window.width - 10 * 5 - 12) / 4; diff --git a/src/components/LoadingSpinner.js b/src/components/LoadingSpinner/LoadingSpinner.js similarity index 71% rename from src/components/LoadingSpinner.js rename to src/components/LoadingSpinner/LoadingSpinner.js index 8ec53f9..0cb6f6d 100644 --- a/src/components/LoadingSpinner.js +++ b/src/components/LoadingSpinner/LoadingSpinner.js @@ -4,10 +4,11 @@ import { Text, ActivityIndicator } from 'react-native'; -import mainStyles from '../styles/components/_Main'; -import indicatorStyles from '../styles/common/_Indicator'; -import styles from '../styles/components/_LoadingSpinner'; -import TIPS from '../constants/funnyTips'; +import TIPS from '~/constants/funnyTips'; + +import mainStyles from '~/common/styles/Main.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; +import styles from './LoadingSpinner.style'; export default class LoadingSpinner extends Component { render() { diff --git a/src/styles/components/_LoadingSpinner.js b/src/components/LoadingSpinner/LoadingSpinner.style.js similarity index 78% rename from src/styles/components/_LoadingSpinner.js rename to src/components/LoadingSpinner/LoadingSpinner.style.js index 631b121..811f70a 100644 --- a/src/styles/components/_LoadingSpinner.js +++ b/src/components/LoadingSpinner/LoadingSpinner.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/modal/LoginModal.js b/src/components/LoginModal/LoginModal.js similarity index 89% rename from src/components/modal/LoginModal.js rename to src/components/LoginModal/LoginModal.js index a7b902a..63913ba 100644 --- a/src/components/modal/LoginModal.js +++ b/src/components/LoginModal/LoginModal.js @@ -10,22 +10,23 @@ import { Navigator, findNodeHandle } from 'react-native'; +import Button from 'apsl-react-native-button'; import { connect } from 'react-redux'; import { NavigationActions } from 'react-navigation'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; -import { PopButton } from '../../components/button'; -import Button from 'apsl-react-native-button'; -import mainStyles from '../../styles/components/_Main'; -import styles from '../../styles/components/modal/_LoginModal'; -import Header from '../Header'; -import SafariView from '../../services/SafariView'; -import { REGISTER_URL } from '../../config'; +import PopButton from '~/components/PopButton/PopButton'; +import Header from '~/components/Header/Header'; +import SafariView from '~/services/SafariView'; +import { REGISTER_URL } from '~/config'; import { userLogin, resetAuthrization, resetAuthrizationResult, cleanCache -} from '../../actions/authorizeAction'; +} from '~/actions/authorizeAction'; + +import mainStyles from '~/common/styles/Main.style'; +import styles from './LoginModal.style'; const resetAction = NavigationActions.reset({ index: 0, @@ -95,7 +96,7 @@ class LoginModal extends Component { return (
@@ -110,7 +111,7 @@ class LoginModal extends Component { + source={require('~/images/logo_transparent.png')} /> + source={require('~/images/noavatar.jpg')} /> } {token ? userName : '请先登录'} diff --git a/src/styles/components/_MenuProfile.js b/src/components/MenuProfile/MenuProfile.style.js similarity index 93% rename from src/styles/components/_MenuProfile.js rename to src/components/MenuProfile/MenuProfile.style.js index 7030e0c..d77b7a1 100644 --- a/src/styles/components/_MenuProfile.js +++ b/src/components/MenuProfile/MenuProfile.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ menuHeader: { diff --git a/src/components/NotifyItem.js b/src/components/NotifyItem/NotifyItem.js similarity index 93% rename from src/components/NotifyItem.js rename to src/components/NotifyItem/NotifyItem.js index 900c070..0357bd2 100644 --- a/src/components/NotifyItem.js +++ b/src/components/NotifyItem/NotifyItem.js @@ -5,10 +5,11 @@ import { TouchableHighlight } from 'react-native'; import Button from 'apsl-react-native-button'; -import Avatar from './Avatar'; import moment from 'moment'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_NotifyItem'; +import Avatar from '~/components/Avatar/Avatar'; + +import colors from '~/common/styles/colors.style'; +import styles from './NotifyItem.style'; export default class NotifyItem extends Component { render() { diff --git a/src/styles/components/_NotifyItem.js b/src/components/NotifyItem/NotifyItem.style.js similarity index 95% rename from src/styles/components/_NotifyItem.js rename to src/components/NotifyItem/NotifyItem.style.js index ecbb40e..495545b 100644 --- a/src/styles/components/_NotifyItem.js +++ b/src/components/NotifyItem/NotifyItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/NotifyList.js b/src/components/NotifyList/NotifyList.js similarity index 90% rename from src/components/NotifyList.js rename to src/components/NotifyList/NotifyList.js index 493d0fb..17bcbb4 100644 --- a/src/components/NotifyList.js +++ b/src/components/NotifyList/NotifyList.js @@ -6,10 +6,11 @@ import { RefreshControl, ActivityIndicator } from 'react-native'; -import listStyles from '../styles/common/_List'; -import indicatorStyles from '../styles/common/_Indicator'; -import NotifyItem from './NotifyItem'; -import NotifySystemItem from './NotifySystemItem'; +import NotifyItem from '~/components/NotifyItem/NotifyItem'; +import NotifySystemItem from '~/components/NotifySystemItem/NotifySystemItem'; + +import listStyles from '~/common/styles/List.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; export default class NotifyList extends Component { componentDidMount() { diff --git a/src/components/NotifySystemItem.js b/src/components/NotifySystemItem/NotifySystemItem.js similarity index 88% rename from src/components/NotifySystemItem.js rename to src/components/NotifySystemItem/NotifySystemItem.js index e8ccc81..0171f28 100644 --- a/src/components/NotifySystemItem.js +++ b/src/components/NotifySystemItem/NotifySystemItem.js @@ -3,9 +3,10 @@ import { View, Text } from 'react-native'; -import Avatar from './Avatar'; import moment from 'moment'; -import styles from '../styles/components/_NotifyItem'; +import Avatar from '~/components/Avatar/Avatar'; + +import styles from '~/components/NotifyItem/NotifyItem.style'; export default class NotifyItem extends Component { render() { diff --git a/src/components/Picker.js b/src/components/Picker/Picker.js similarity index 91% rename from src/components/Picker.js rename to src/components/Picker/Picker.js index 2d6e28d..9d7089e 100644 --- a/src/components/Picker.js +++ b/src/components/Picker/Picker.js @@ -5,9 +5,10 @@ import { Modal, PickerIOS } from 'react-native'; -import modalStyles from '../styles/common/_Modal'; -import styles from '../styles/components/_Picker'; -import Header from './Header'; +import Header from '~/components/Header/Header'; + +import modalStyles from '~/common/styles/Modal.style'; +import styles from './Picker.style'; export default class Picker extends Component { constructor(props) { diff --git a/src/styles/components/_Picker.js b/src/components/Picker/Picker.style.js similarity index 86% rename from src/styles/components/_Picker.js rename to src/components/Picker/Picker.style.js index 4273202..0c89b16 100644 --- a/src/styles/components/_Picker.js +++ b/src/components/Picker/Picker.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ backdrop: { diff --git a/src/components/PmSessionItem.js b/src/components/PmSessionItem/PmSessionItem.js similarity index 92% rename from src/components/PmSessionItem.js rename to src/components/PmSessionItem/PmSessionItem.js index 4c233c7..5077dc4 100644 --- a/src/components/PmSessionItem.js +++ b/src/components/PmSessionItem/PmSessionItem.js @@ -4,10 +4,11 @@ import { Text, TouchableHighlight } from 'react-native'; -import Avatar from './Avatar'; import moment from 'moment'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_PmSessionItem'; +import Avatar from '~/components/Avatar/Avatar'; + +import colors from '~/common/styles/colors.style'; +import styles from './PmSessionItem.style'; export default class PmSessionItem extends Component { handleOnPress(isNew, plid, userId) { diff --git a/src/styles/components/_PmSessionItem.js b/src/components/PmSessionItem/PmSessionItem.style.js similarity index 94% rename from src/styles/components/_PmSessionItem.js rename to src/components/PmSessionItem/PmSessionItem.style.js index 494e68c..b937802 100644 --- a/src/styles/components/_PmSessionItem.js +++ b/src/components/PmSessionItem/PmSessionItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/PmSessionList.js b/src/components/PmSessionList/PmSessionList.js similarity index 92% rename from src/components/PmSessionList.js rename to src/components/PmSessionList/PmSessionList.js index 8c4b283..9c44f3d 100644 --- a/src/components/PmSessionList.js +++ b/src/components/PmSessionList/PmSessionList.js @@ -6,9 +6,10 @@ import { RefreshControl, ActivityIndicator } from 'react-native'; -import listStyles from '../styles/common/_List'; -import indicatorStyles from '../styles/common/_Indicator'; -import PmSessionItem from './PmSessionItem'; +import PmSessionItem from '~/components/PmSessionItem/PmSessionItem'; + +import listStyles from '~/common/styles/List.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; export default class PrivateList extends Component { componentDidMount() { diff --git a/src/components/button/PopButton.js b/src/components/PopButton/PopButton.js similarity index 100% rename from src/components/button/PopButton.js rename to src/components/PopButton/PopButton.js diff --git a/src/components/ProgressImage.js b/src/components/ProgressImage/ProgressImage.js similarity index 91% rename from src/components/ProgressImage.js rename to src/components/ProgressImage/ProgressImage.js index 7d98ac6..f89515a 100644 --- a/src/components/ProgressImage.js +++ b/src/components/ProgressImage/ProgressImage.js @@ -6,9 +6,10 @@ import { ActivityIndicator, TouchableHighlight } from 'react-native'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_ProgressImage'; -import SafariView from '../services/SafariView'; +import SafariView from '~/services/SafariView'; + +import colors from '~/common/styles/colors.style'; +import styles from './ProgressImage.style'; export default class ProgressImage extends Component { // constructor(props) { @@ -82,7 +83,7 @@ export default class ProgressImage extends Component { {isLoadError && 图片加载失败或图片已失效 @@ -91,7 +92,7 @@ export default class ProgressImage extends Component { this.setState({ isLoading: true })} onLoadEnd={() => this.setState({ isLoading: false })} onError={() => this.setState({ isLoadError: true })} diff --git a/src/styles/components/_ProgressImage.js b/src/components/ProgressImage/ProgressImage.style.js similarity index 92% rename from src/styles/components/_ProgressImage.js rename to src/components/ProgressImage/ProgressImage.style.js index 1b20a21..03f148e 100644 --- a/src/styles/components/_ProgressImage.js +++ b/src/components/ProgressImage/ProgressImage.style.js @@ -2,7 +2,7 @@ import { StyleSheet, Dimensions } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; const window = Dimensions.get('window'); const IMAGE_HEIGHT = 250; diff --git a/src/components/button/PublishButton.js b/src/components/PublishButton/PublishButton.js similarity index 81% rename from src/components/button/PublishButton.js rename to src/components/PublishButton/PublishButton.js index f77fcf8..697171a 100644 --- a/src/components/button/PublishButton.js +++ b/src/components/PublishButton/PublishButton.js @@ -1,7 +1,8 @@ import React, { Component } from 'react'; import { View } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -import headerRightButtonStyles from '../../styles/components/button/_HeaderRightButton'; + +import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; export default class PublishButton extends Component { render() { diff --git a/src/components/modal/PublishModal.js b/src/components/PublishModal/PublishModal.js similarity index 94% rename from src/components/modal/PublishModal.js rename to src/components/PublishModal/PublishModal.js index ee1b1ad..db85777 100644 --- a/src/components/modal/PublishModal.js +++ b/src/components/PublishModal/PublishModal.js @@ -10,27 +10,27 @@ import { ActivityIndicator, LayoutAnimation } from 'react-native'; -import LoadingSpinnerOverlay from '../3rd_party/LoadingSpinnerOverlay'; -import { isIphoneX } from 'react-native-iphone-x-helper'; +import Icon from 'react-native-vector-icons/FontAwesome'; +import _ from 'lodash'; import { connect } from 'react-redux'; import { NavigationActions } from 'react-navigation'; -import Icon from 'react-native-vector-icons/FontAwesome'; +import { isIphoneX } from 'react-native-iphone-x-helper'; import KeyboardAccessory from 'react-native-sticky-keyboard-accessory'; import EmojiPicker from 'react-native-smart-emoji-picker'; -import _ from 'lodash'; -import mainStyles from '../../styles/components/_Main'; -import modalStyles from '../../styles/common/_Modal'; -import styles from '../../styles/components/modal/_PublishModal'; -import keyboardAccessoryStyles from '../../styles/components/_KeyboardAccessory'; -import colors from '../../styles/common/_colors'; -import Header from '../Header'; -import Picker from '../Picker'; -import ImageUploader from '../ImageUploader'; -import MessageBar from '../../services/MessageBar'; -import { CUSTOM_EMOJIS } from '../../constants/emojis'; - -import api from '../../services/api'; -import { invalidateTopicList, fetchTopicList } from '../../actions/topic/topicListAction'; +import LoadingSpinnerOverlay from '~/common/vendor/components/LoadingSpinnerOverlay'; +import Header from '~/components/Header/Header'; +import Picker from '~/components/Picker/Picker'; +import ImageUploader from '~/components/ImageUploader/ImageUploader'; +import MessageBar from '~/services/MessageBar'; +import api from '~/services/api'; +import { CUSTOM_EMOJIS } from '~/constants/emojis'; +import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; + +import mainStyles from '~/common/styles/Main.style'; +import modalStyles from '~/common/styles/Modal.style'; +import keyboardAccessoryStyles from '~/common/styles/KeyboardAccessory.style'; +import colors from '~/common/styles/colors.style'; +import styles from './PublishModal.style'; const resetAction = NavigationActions.reset({ index: 0, diff --git a/src/styles/components/modal/_PublishModal.js b/src/components/PublishModal/PublishModal.style.js similarity index 93% rename from src/styles/components/modal/_PublishModal.js rename to src/components/PublishModal/PublishModal.style.js index 5ed8978..4982b3d 100644 --- a/src/styles/components/modal/_PublishModal.js +++ b/src/components/PublishModal/PublishModal.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ form: { diff --git a/src/components/modal/ReplyModal.js b/src/components/ReplyModal/ReplyModal.js similarity index 93% rename from src/components/modal/ReplyModal.js rename to src/components/ReplyModal/ReplyModal.js index 714d5a1..6eeda79 100644 --- a/src/components/modal/ReplyModal.js +++ b/src/components/ReplyModal/ReplyModal.js @@ -10,20 +10,21 @@ import { TouchableHighlight, ActivityIndicator } from 'react-native'; -import LoadingSpinnerOverlay from '../3rd_party/LoadingSpinnerOverlay'; import Icon from 'react-native-vector-icons/FontAwesome'; import KeyboardAccessory from 'react-native-sticky-keyboard-accessory'; import EmojiPicker from 'react-native-smart-emoji-picker'; -import mainStyles from '../../styles/components/_Main'; -import modalStyles from '../../styles/common/_Modal'; -import styles from '../../styles/components/modal/_ReplyModal'; -import keyboardAccessoryStyles from '../../styles/components/_KeyboardAccessory'; -import Header from '../Header'; -import MessageBar from '../../services/MessageBar'; -import ImageUploader from '../ImageUploader'; -import api from '../../services/api'; -import { fetchTopic } from '../../actions/topic/topicAction'; -import { CUSTOM_EMOJIS } from '../../constants/emojis'; +import LoadingSpinnerOverlay from '~/common/vendor/components/LoadingSpinnerOverlay'; +import Header from '~/components/Header/Header'; +import ImageUploader from '~/components/ImageUploader/ImageUploader'; +import MessageBar from '~/services/MessageBar'; +import api from '~/services/api'; +import { CUSTOM_EMOJIS } from '~/constants/emojis'; +import { fetchTopic } from '~/actions/topic/topicAction'; + +import mainStyles from '~/common/styles/Main.style'; +import modalStyles from '~/common/styles/Modal.style'; +import keyboardAccessoryStyles from '~/common/styles/KeyboardAccessory.style'; +import styles from './ReplyModal.style'; class ReplyModal extends Component { constructor(props) { diff --git a/src/styles/components/modal/_ReplyModal.js b/src/components/ReplyModal/ReplyModal.style.js similarity index 92% rename from src/styles/components/modal/_ReplyModal.js rename to src/components/ReplyModal/ReplyModal.style.js index c58f64f..aa2101d 100644 --- a/src/styles/components/modal/_ReplyModal.js +++ b/src/components/ReplyModal/ReplyModal.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ disabledForm: { diff --git a/src/components/RewardList.js b/src/components/RewardList/RewardList.js similarity index 94% rename from src/components/RewardList.js rename to src/components/RewardList/RewardList.js index 0f33bb9..29f7b1c 100644 --- a/src/components/RewardList.js +++ b/src/components/RewardList/RewardList.js @@ -3,9 +3,10 @@ import { View, Text, } from 'react-native'; -import Avatar from './Avatar'; import Icon from 'react-native-vector-icons/FontAwesome'; -import styles from '../styles/components/_RewardList'; +import Avatar from '~/components/Avatar/Avatar'; + +import styles from './RewardList.style'; export default class RewardList extends Component { render() { diff --git a/src/styles/components/_RewardList.js b/src/components/RewardList/RewardList.style.js similarity index 92% rename from src/styles/components/_RewardList.js rename to src/components/RewardList/RewardList.style.js index ce67505..ede0ab9 100644 --- a/src/styles/components/_RewardList.js +++ b/src/components/RewardList/RewardList.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ reward: { diff --git a/src/components/SettingItem.js b/src/components/SettingItem/SettingItem.js similarity index 90% rename from src/components/SettingItem.js rename to src/components/SettingItem/SettingItem.js index 0dbfafc..e81be5f 100644 --- a/src/components/SettingItem.js +++ b/src/components/SettingItem/SettingItem.js @@ -6,8 +6,9 @@ import { TouchableHighlight } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -import styles from '../styles/components/_SettingItem'; -import colors from '../styles/common/_colors'; + +import colors from '~/common/styles/colors.style'; +import styles from './SettingItem.style'; export default class SettingItem extends Component { render() { diff --git a/src/styles/components/_SettingItem.js b/src/components/SettingItem/SettingItem.style.js similarity index 93% rename from src/styles/components/_SettingItem.js rename to src/components/SettingItem/SettingItem.style.js index 53a7cba..46ffead 100644 --- a/src/styles/components/_SettingItem.js +++ b/src/components/SettingItem/SettingItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ item: { diff --git a/src/components/SettingSwitchItem.js b/src/components/SettingSwitchItem/SettingSwitchItem.js similarity index 81% rename from src/components/SettingSwitchItem.js rename to src/components/SettingSwitchItem/SettingSwitchItem.js index 072773d..3849c74 100644 --- a/src/components/SettingSwitchItem.js +++ b/src/components/SettingSwitchItem/SettingSwitchItem.js @@ -4,8 +4,9 @@ import { Text, Switch, } from 'react-native'; -import mainStyles from '../styles/components/_SettingItem'; -import styles from '../styles/components/_SettingSwitchItem'; + +import mainStyles from '~/components/SettingItem/SettingItem.style'; +import styles from './SettingSwitchItem.style'; export default class SettingItem extends Component { render() { diff --git a/src/styles/components/_SettingSwitchItem.js b/src/components/SettingSwitchItem/SettingSwitchItem.style.js similarity index 75% rename from src/styles/components/_SettingSwitchItem.js rename to src/components/SettingSwitchItem/SettingSwitchItem.style.js index 62593de..72886de 100644 --- a/src/styles/components/_SettingSwitchItem.js +++ b/src/components/SettingSwitchItem/SettingSwitchItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ indicator: { diff --git a/src/components/SubForumItem.js b/src/components/SubForumItem/SubForumItem.js similarity index 90% rename from src/components/SubForumItem.js rename to src/components/SubForumItem/SubForumItem.js index bf2c540..d8a9a06 100644 --- a/src/components/SubForumItem.js +++ b/src/components/SubForumItem/SubForumItem.js @@ -6,9 +6,10 @@ import { TouchableHighlight } from 'react-native'; import moment from 'moment'; -import colors from '../styles/common/_colors'; -import styles from '../styles/components/_SubForumItem'; -import FORUMS from '../constants/forums'; +import FORUMS from '~/constants/forums'; + +import colors from '~/common/styles/colors.style'; +import styles from './SubForumItem.style'; export default class SubForumItem extends Component { render() { @@ -26,7 +27,7 @@ export default class SubForumItem extends Component { } } = this.props; - let boardImage = FORUMS[board_id] || require('../images/board_img/default.png'); + let boardImage = FORUMS[board_id] || require('~/images/board_img/default.png'); last_posts_date = moment(+last_posts_date).startOf('minute').fromNow(); return ( diff --git a/src/styles/components/_SubForumItem.js b/src/components/SubForumItem/SubForumItem.style.js similarity index 95% rename from src/styles/components/_SubForumItem.js rename to src/components/SubForumItem/SubForumItem.style.js index ba596a0..4c7926f 100644 --- a/src/styles/components/_SubForumItem.js +++ b/src/components/SubForumItem/SubForumItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ subForum: { diff --git a/src/components/SubForumList.js b/src/components/SubForumList/SubForumList.js similarity index 87% rename from src/components/SubForumList.js rename to src/components/SubForumList/SubForumList.js index 6d530d5..506bd4c 100644 --- a/src/components/SubForumList.js +++ b/src/components/SubForumList/SubForumList.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { View } from 'react-native'; -import SubForumItem from './SubForumItem'; +import SubForumItem from '~/components/SubForumItem/SubForumItem'; export default class SubForumList extends Component { render() { diff --git a/src/components/TopicItem.js b/src/components/TopicItem/TopicItem.js similarity index 94% rename from src/components/TopicItem.js rename to src/components/TopicItem/TopicItem.js index 7ea51f9..032c7be 100644 --- a/src/components/TopicItem.js +++ b/src/components/TopicItem/TopicItem.js @@ -4,14 +4,15 @@ import { Text, TouchableHighlight } from 'react-native'; -import Avatar from './Avatar'; import Icon from 'react-native-vector-icons/FontAwesome'; import moment from 'moment'; // Refer to this issue https://github.com/moment/momentjs.com/pull/241 import 'moment/locale/zh-cn'; -import { AVATAR_ROOT } from '../config'; -import styles from '../styles/components/_TopicItem'; -import colors from '../styles/common/_colors'; +import Avatar from '~/components/Avatar/Avatar'; +import { AVATAR_ROOT } from '~/config'; + +import colors from '~/common/styles/colors.style'; +import styles from './TopicItem.style'; export default class TopicItem extends Component { handleOnPress(topic) { diff --git a/src/styles/components/_TopicItem.js b/src/components/TopicItem/TopicItem.style.js similarity index 96% rename from src/styles/components/_TopicItem.js rename to src/components/TopicItem/TopicItem.style.js index b900e7d..503b332 100644 --- a/src/styles/components/_TopicItem.js +++ b/src/components/TopicItem/TopicItem.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/components/TopicList.js b/src/components/TopicList/TopicList.js similarity index 94% rename from src/components/TopicList.js rename to src/components/TopicList/TopicList.js index 40c51b2..510aeb5 100644 --- a/src/components/TopicList.js +++ b/src/components/TopicList/TopicList.js @@ -6,10 +6,11 @@ import { RefreshControl, ActivityIndicator } from 'react-native'; -import { AVATAR_ROOT } from '../config'; -import listStyles from '../styles/common/_List'; -import indicatorStyles from '../styles/common/_Indicator'; -import TopicItem from './TopicItem'; +import TopicItem from '~/components/TopicItem/TopicItem'; +import { AVATAR_ROOT } from '~/config'; + +import listStyles from '~/common/styles/List.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; export default class TopicList extends Component { endReached() { diff --git a/src/components/VoteList.js b/src/components/VoteList/VoteList.js similarity index 98% rename from src/components/VoteList.js rename to src/components/VoteList/VoteList.js index 4a754a0..eb58298 100644 --- a/src/components/VoteList.js +++ b/src/components/VoteList/VoteList.js @@ -6,7 +6,8 @@ import { } from 'react-native'; import CheckBox from 'react-native-checkbox'; import Button from 'apsl-react-native-button'; -import styles from '../styles/components/_VoteList'; + +import styles from './VoteList.style'; const progressTintColors = [ '#e92725', diff --git a/src/styles/components/_VoteList.js b/src/components/VoteList/VoteList.style.js similarity index 96% rename from src/styles/components/_VoteList.js rename to src/components/VoteList/VoteList.style.js index 677d67f..cfb5e9f 100644 --- a/src/styles/components/_VoteList.js +++ b/src/components/VoteList/VoteList.style.js @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native'; import Dimensions from 'Dimensions'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; const window = Dimensions.get('window'); diff --git a/src/components/button/index.js b/src/components/button/index.js deleted file mode 100644 index 7dfffdc..0000000 --- a/src/components/button/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import MenuButton from './MenuButton'; -import PublishButton from './PublishButton'; -import PopButton from './PopButton'; - -export { - MenuButton, - PublishButton, - PopButton -}; diff --git a/src/constants/forums.js b/src/constants/forums.js index 76e7322..6bbd8c6 100644 --- a/src/constants/forums.js +++ b/src/constants/forums.js @@ -2,42 +2,42 @@ // but we have to do in this way due to React Native limitation. // https://github.com/facebook/react-native/issues/2481 export default { - 108: require('../images/board_img/108.png'), - 109: require('../images/board_img/109.png'), - 111: require('../images/board_img/111.png'), - 114: require('../images/board_img/114.png'), - 115: require('../images/board_img/115.png'), - 118: require('../images/board_img/118.png'), - 121: require('../images/board_img/121.png'), - 140: require('../images/board_img/140.png'), - 149: require('../images/board_img/149.png'), - 17: require('../images/board_img/17.png'), - 174: require('../images/board_img/174.png'), - 2: require('../images/board_img/2.png'), - 20: require('../images/board_img/20.png'), - 211: require('../images/board_img/211.png'), - 219: require('../images/board_img/219.png'), - 225: require('../images/board_img/225.png'), - 236: require('../images/board_img/236.png'), - 237: require('../images/board_img/237.png'), - 244: require('../images/board_img/244.png'), - 25: require('../images/board_img/25.png'), - 255: require('../images/board_img/255.png'), - 258: require('../images/board_img/258.png'), - 272: require('../images/board_img/272.png'), - 309: require('../images/board_img/309.png'), - 312: require('../images/board_img/312.png'), - 316: require('../images/board_img/316.png'), - 326: require('../images/board_img/326.png'), - 334: require('../images/board_img/334.png'), - 370: require('../images/board_img/370.png'), - 382: require('../images/board_img/382.png'), - 45: require('../images/board_img/45.png'), - 46: require('../images/board_img/46.png'), - 55: require('../images/board_img/55.png'), - 61: require('../images/board_img/61.png'), - 66: require('../images/board_img/66.png'), - 70: require('../images/board_img/70.png'), - 74: require('../images/board_img/74.png'), - 99: require('../images/board_img/99.png'), + 108: require('~/images/board_img/108.png'), + 109: require('~/images/board_img/109.png'), + 111: require('~/images/board_img/111.png'), + 114: require('~/images/board_img/114.png'), + 115: require('~/images/board_img/115.png'), + 118: require('~/images/board_img/118.png'), + 121: require('~/images/board_img/121.png'), + 140: require('~/images/board_img/140.png'), + 149: require('~/images/board_img/149.png'), + 17: require('~/images/board_img/17.png'), + 174: require('~/images/board_img/174.png'), + 2: require('~/images/board_img/2.png'), + 20: require('~/images/board_img/20.png'), + 211: require('~/images/board_img/211.png'), + 219: require('~/images/board_img/219.png'), + 225: require('~/images/board_img/225.png'), + 236: require('~/images/board_img/236.png'), + 237: require('~/images/board_img/237.png'), + 244: require('~/images/board_img/244.png'), + 25: require('~/images/board_img/25.png'), + 255: require('~/images/board_img/255.png'), + 258: require('~/images/board_img/258.png'), + 272: require('~/images/board_img/272.png'), + 309: require('~/images/board_img/309.png'), + 312: require('~/images/board_img/312.png'), + 316: require('~/images/board_img/316.png'), + 326: require('~/images/board_img/326.png'), + 334: require('~/images/board_img/334.png'), + 370: require('~/images/board_img/370.png'), + 382: require('~/images/board_img/382.png'), + 45: require('~/images/board_img/45.png'), + 46: require('~/images/board_img/46.png'), + 55: require('~/images/board_img/55.png'), + 61: require('~/images/board_img/61.png'), + 66: require('~/images/board_img/66.png'), + 70: require('~/images/board_img/70.png'), + 74: require('~/images/board_img/74.png'), + 99: require('~/images/board_img/99.png'), }; diff --git a/src/containers/About.js b/src/containers/About/About.js similarity index 79% rename from src/containers/About.js rename to src/containers/About/About.js index c54ace8..5a37873 100644 --- a/src/containers/About.js +++ b/src/containers/About/About.js @@ -9,17 +9,17 @@ import { TouchableHighlight } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -import SettingItem from '../components/SettingItem'; -import menus from '../constants/menus'; -import mainStyles from '../styles/components/_Main'; -import styles from '../styles/containers/_About'; -import colors from '../styles/common/_colors'; -import * as configs from '../config'; -import SafariView from '../services/SafariView'; +import SettingItem from '~/components/SettingItem/SettingItem'; +import SafariView from '~/services/SafariView'; +import MENUS from '~/constants/menus'; +import * as configs from '~/config'; + +import mainStyles from '~/common/styles/Main.style'; +import styles from './About.style'; export default class About extends Component { static navigationOptions = { - title: menus.about.title + title: MENUS.about.title } render() { @@ -30,7 +30,7 @@ export default class About extends Component { + source={require('~/images/new_logo.png')} /> 清水河畔 {configs.VERSION} diff --git a/src/styles/containers/_About.js b/src/containers/About/About.style.js similarity index 91% rename from src/styles/containers/_About.js rename to src/containers/About/About.style.js index ad5fccc..960ef3c 100644 --- a/src/styles/containers/_About.js +++ b/src/containers/About/About.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/containers/App.js b/src/containers/App/App.js similarity index 67% rename from src/containers/App.js rename to src/containers/App/App.js index 1ad85e3..15c2ccb 100644 --- a/src/containers/App.js +++ b/src/containers/App/App.js @@ -1,8 +1,8 @@ import React, { Component } from 'react'; import { Provider } from 'react-redux'; -import configureStore from '../store/configureStore'; -import rootSaga from '../sagas'; -import Navigator from './Navigator'; +import configureStore from '~/store/configureStore'; +import rootSaga from '~/sagas'; +import Navigator from '~/containers/Navigator/Navigator'; const store = configureStore(); store.runSaga(rootSaga); diff --git a/src/containers/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js similarity index 91% rename from src/containers/ForumDetail.js rename to src/containers/ForumDetail/ForumDetail.js index 93d755c..6b017f2 100644 --- a/src/containers/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -7,15 +7,16 @@ import { } from 'react-native'; import _ from 'lodash'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import mainStyles from '../styles/components/_Main'; -import scrollableTabViewStyles from '../styles/common/_ScrollableTabView'; -import colors from '../styles/common/_colors'; -import TopicList from '../components/TopicList'; -import ForumItems from '../components/ForumItems'; -import PublishModal from '../components/modal/PublishModal'; -import { PublishButton } from '../components/button'; -import { invalidateTopicList, fetchTopicList, resetTopicList } from '../actions/topic/topicListAction'; -import { invalidateForumList, fetchForumList } from '../actions/forumAction'; +import TopicList from '~/components/TopicList/TopicList'; +import ForumItems from '~/components/ForumItems/ForumItems'; +import PublishModal from '~/components/PublishModal/PublishModal'; +import PublishButton from '~/components/PublishButton/PublishButton'; +import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/actions/topic/topicListAction'; +import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; + +import mainStyles from '~/common/styles/Main.style'; +import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; +import colors from '~/common/styles/colors.style'; const TABS = [ { label: '最新回复', type: 'all' }, diff --git a/src/containers/ForumList.js b/src/containers/ForumList/ForumList.js similarity index 82% rename from src/containers/ForumList.js rename to src/containers/ForumList/ForumList.js index 5e97058..312720d 100644 --- a/src/containers/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -6,14 +6,15 @@ import { RefreshControl } from 'react-native'; import _ from 'lodash'; -import mainStyles from '../styles/components/_Main'; -import ForumItems from '../components/ForumItems'; -import menus from '../constants/menus'; -import { invalidateForumList, fetchForumList } from '../actions/forumAction'; +import ForumItems from '~/components/ForumItems/ForumItems'; +import MENUS from '~/constants/menus'; +import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; + +import mainStyles from '~/common/styles/Main.style'; class ForumList extends Component { static navigationOptions = { - title: menus.forumList.title + title: MENUS.forumList.title } constructor(props) { diff --git a/src/containers/Home.js b/src/containers/Home/Home.js similarity index 85% rename from src/containers/Home.js rename to src/containers/Home/Home.js index 8519192..667aa93 100644 --- a/src/containers/Home.js +++ b/src/containers/Home/Home.js @@ -6,14 +6,16 @@ import { import { connect } from 'react-redux'; import _ from 'lodash'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import scrollableTabViewStyles from '../styles/common/_ScrollableTabView'; -import colors from '../styles/common/_colors'; -import mainStyles from '../styles/components/_Main'; -import Header from '../components/Header'; -import TopicList from '../components/TopicList'; -import { MenuButton, PublishButton } from '../components/button'; -import { invalidateTopicList, fetchTopicList } from '../actions/topic/topicListAction'; -import { getAlertCount } from '../selectors/alert'; +import Header from '~/components/Header/Header'; +import TopicList from '~/components/TopicList/TopicList'; +import MenuButton from '~/components/MenuButton/MenuButton'; +import PublishButton from '~/components/PublishButton/PublishButton'; +import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; +import { getAlertCount } from '~/selectors/alert'; + +import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; +import mainStyles from '~/common/styles/Main.style'; +import colors from '~/common/styles/colors.style'; const TABS = [ { label: '最新回复', type: 'all' }, diff --git a/src/containers/Individual.js b/src/containers/Individual/Individual.js similarity index 90% rename from src/containers/Individual.js rename to src/containers/Individual/Individual.js index 9af4f4b..510f53c 100644 --- a/src/containers/Individual.js +++ b/src/containers/Individual/Individual.js @@ -7,18 +7,19 @@ import { ScrollView, TouchableOpacity } from 'react-native'; -import { HeaderBackButton } from 'react-navigation'; import _ from 'lodash'; -import ScrollableTabView from 'react-native-scrollable-tab-view'; import Icon from 'react-native-vector-icons/FontAwesome'; -import TopicList from '../components/TopicList'; -import colors from '../styles/common/_colors'; -import scrollableTabViewStyles from '../styles/common/_ScrollableTabView'; -import headerRightButtonStyles from '../styles/components/button/_HeaderRightButton'; -import mainStyles from '../styles/components/_Main'; -import styles from '../styles/containers/_Individual'; -import { invalidateUserTopicList, fetchUserTopicList } from '../actions/user/topicListAction'; -import { AVATAR_ROOT } from '../config'; +import ScrollableTabView from 'react-native-scrollable-tab-view'; +import { HeaderBackButton } from 'react-navigation'; +import TopicList from '~/components/TopicList/TopicList'; +import { invalidateUserTopicList, fetchUserTopicList } from '~/actions/user/topicListAction'; +import { AVATAR_ROOT } from '~/config'; + +import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; +import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; +import mainStyles from '~/common/styles/Main.style'; +import colors from '~/common/styles/colors.style'; +import styles from './Individual.style'; class Individual extends Component { static navigationOptions = ({ navigation }) => { diff --git a/src/styles/containers/_Individual.js b/src/containers/Individual/Individual.style.js similarity index 88% rename from src/styles/containers/_Individual.js rename to src/containers/Individual/Individual.style.js index 00fad09..d604bfb 100644 --- a/src/styles/containers/_Individual.js +++ b/src/containers/Individual/Individual.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ // nav: { diff --git a/src/containers/Information.js b/src/containers/Information/Information.js similarity index 82% rename from src/containers/Information.js rename to src/containers/Information/Information.js index 49438fc..787df28 100644 --- a/src/containers/Information.js +++ b/src/containers/Information/Information.js @@ -3,20 +3,21 @@ import { connect } from 'react-redux'; import { View } from 'react-native'; import _ from 'lodash'; import Icon from 'react-native-vector-icons/FontAwesome'; -import ImagePicker from '../services/ImagePicker'; -import { setAuthrization } from '../actions/authorizeAction'; -import menus from '../constants/menus'; -import SettingItem from '../components/SettingItem'; -import LoadingSpinner from '../components/LoadingSpinner'; -import mainStyles from '../styles/components/_Main'; -import indicatorStyles from '../styles/common/_Indicator'; -import styles from '../styles/containers/_About'; -import api from '../services/api'; -import { fetchUser, resetUser } from '../actions/user/userAction'; +import SettingItem from '~/components/SettingItem/SettingItem'; +import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; +import ImagePicker from '~/services/ImagePicker'; +import MENUS from '~/constants/menus'; +import api from '~/services/api'; +import { setAuthrization } from '~/actions/authorizeAction'; +import { fetchUser, resetUser } from '~/actions/user/userAction'; + +import mainStyles from '~/common/styles/Main.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; +import styles from '~/containers/About/About.style'; class Information extends Component { static navigationOptions = { - title: menus.information.title + title: MENUS.information.title } constructor(props) { diff --git a/src/containers/Menu.js b/src/containers/Menu/Menu.js similarity index 74% rename from src/containers/Menu.js rename to src/containers/Menu/Menu.js index 1a013b7..58e88bf 100644 --- a/src/containers/Menu.js +++ b/src/containers/Menu/Menu.js @@ -6,22 +6,22 @@ import { AsyncStorage, ActionSheetIOS, } from 'react-native'; -import { SafeAreaView } from 'react-navigation'; -import { NavigationActions } from 'react-navigation'; -import styles from '../styles/containers/_Menu'; -import LoginModal from '../components/modal/LoginModal'; -import MenuProfile from '../components/MenuProfile'; -import MenuItem from '../components/MenuItem'; -import MenuBottomItem from '../components/MenuBottomItem'; +import { SafeAreaView, NavigationActions } from 'react-navigation'; +import LoginModal from '~/components/LoginModal/LoginModal'; +import MenuProfile from '~/components/MenuProfile/MenuProfile'; +import MenuItem from '~/components/MenuItem/MenuItem'; +import MenuBottomItem from '~/components/MenuBottomItem/MenuBottomItem'; +import MENUS from '~/constants/menus'; import { userLogin, resetAuthrization, resetAuthrizationResult, cleanCache -} from '../actions/authorizeAction'; -import { invalidateTopicList, fetchTopicList } from '../actions/topic/topicListAction'; -import menus from '../constants/menus'; -import { getAlertCount } from '../selectors/alert'; +} from '~/actions/authorizeAction'; +import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; +import { getAlertCount } from '~/selectors/alert'; + +import styles from './Menu.style'; const resetAction = NavigationActions.reset({ index: 0, @@ -73,7 +73,7 @@ class Menu extends Component { forceInset={{ top: 'never' }} style={styles.container}> } {token && this.showLogoutDialog()} /> diff --git a/src/styles/containers/_Menu.js b/src/containers/Menu/Menu.style.js similarity index 94% rename from src/styles/containers/_Menu.js rename to src/containers/Menu/Menu.style.js index e697483..d3a8cc1 100644 --- a/src/styles/containers/_Menu.js +++ b/src/containers/Menu/Menu.style.js @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native'; import Dimensions from 'Dimensions'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; const window = Dimensions.get('window'); diff --git a/src/containers/Message.js b/src/containers/Message/Message.js similarity index 85% rename from src/containers/Message.js rename to src/containers/Message/Message.js index a919fea..1532621 100644 --- a/src/containers/Message.js +++ b/src/containers/Message/Message.js @@ -3,17 +3,18 @@ import { View } from 'react-native'; import { connect } from 'react-redux'; import _ from 'lodash'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import mainStyles from '../styles/components/_Main'; -import scrollableTabViewStyles from '../styles/common/_ScrollableTabView'; -import colors from '../styles/common/_colors'; -import NotifyList from '../components/NotifyList'; -import PmSessionList from '../components/PmSessionList'; -import MessageTabBar from '../components/3rd_party/MessageTabBar'; -import ReplyModal from '../components/modal/ReplyModal'; -import menus from '../constants/menus'; -import { invalidateNotifyList, fetchNotifyList } from '../actions/message/notifyListAction'; -import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '../actions/message/pmSessionListAction'; -import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '../selectors/alert'; +import MessageTabBar from '~/common/vendor/components/MessageTabBar'; +import NotifyList from '~/components/NotifyList/NotifyList'; +import PmSessionList from '~/components/PmSessionList/PmSessionList'; +import ReplyModal from '~/components/ReplyModal/ReplyModal'; +import MENUS from '~/constants/menus'; +import { invalidateNotifyList, fetchNotifyList } from '~/actions/message/notifyListAction'; +import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/actions/message/pmSessionListAction'; +import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; + +import mainStyles from '~/common/styles/Main.style'; +import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; +import colors from '~/common/styles/colors.style'; const TABS = [ { label: '@', type: 'at' }, @@ -24,7 +25,7 @@ const TABS = [ class Message extends Component { static navigationOptions = { - title: menus.message.title + title: MENUS.message.title } fetchNotifyList({ page, isEndReached, notifyType }) { diff --git a/src/containers/Navigator.js b/src/containers/Navigator/Navigator.js similarity index 76% rename from src/containers/Navigator.js rename to src/containers/Navigator/Navigator.js index c68b1dc..fc296f7 100644 --- a/src/containers/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -3,29 +3,30 @@ import { connect } from 'react-redux'; import { View, ScrollView } from 'react-native'; import { DrawerNavigator, StackNavigator, SafeAreaView } from 'react-navigation'; import { MessageBar, MessageBarManager } from 'react-native-message-bar'; -import Menu from './Menu'; -import HomeScreen from './Home'; -import ForumListScreen from './ForumList'; -import ForumScreen from './ForumDetail'; -import SearchScreen from './Search'; -import TopicScreen from './TopicDetail'; -import MessageScreen from './Message'; -import IndividualScreen from './Individual'; -import PrivateMessageScreen from './PmList'; -import AboutScreen from './About'; -import InformationScreen from './Information'; -import SettingsScreen from './Settings'; -import WebPageScreen from './WebPage'; -import LoginModalScreen from '../components/modal/LoginModal'; -import PublishModalScreen from '../components/modal/PublishModal'; -import ReplyModalScreen from '../components/modal/ReplyModal'; -import ForumListModalScreen from '../components/modal/ForumListModal'; -import FriendListModalScreen from '../components/modal/FriendListModal'; -import colors from '../styles/common/_colors'; -import { getUserFromStorage } from '../actions/authorizeAction'; -import { getSettingsFromStorage } from '../actions/settingsAction'; -import { fetchAlerts } from '../actions/message/alertAction'; -import { ALERT_POLL_FREQUENCY } from '../config'; +import Menu from '~/containers/Menu/Menu'; +import HomeScreen from '~/containers/Home/Home'; +import ForumListScreen from '~/containers/ForumList/ForumList'; +import ForumScreen from '~/containers/ForumDetail/ForumDetail'; +import SearchScreen from '~/containers/Search/Search'; +import TopicScreen from '~/containers/TopicDetail/TopicDetail'; +import MessageScreen from '~/containers/Message/Message'; +import IndividualScreen from '~/containers/Individual/Individual'; +import PrivateMessageScreen from '~/containers/PmList/PmList'; +import AboutScreen from '~/containers/About/About'; +import InformationScreen from '~/containers/Information/Information'; +import SettingsScreen from '~/containers/Settings/Settings'; +import WebPageScreen from '~/containers/WebPage/WebPage'; +import LoginModalScreen from '~/components/LoginModal/LoginModal'; +import PublishModalScreen from '~/components/PublishModal/PublishModal'; +import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; +import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; +import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; +import { getUserFromStorage } from '~/actions/authorizeAction'; +import { getSettingsFromStorage } from '~/actions/settingsAction'; +import { fetchAlerts } from '~/actions/message/alertAction'; +import { ALERT_POLL_FREQUENCY } from '~/config'; + +import colors from '~/common/styles/colors.style'; const AppNavigator = DrawerNavigator({ App: { diff --git a/src/containers/PmList.js b/src/containers/PmList/PmList.js similarity index 90% rename from src/containers/PmList.js rename to src/containers/PmList/PmList.js index 0baaae8..96b278c 100644 --- a/src/containers/PmList.js +++ b/src/containers/PmList/PmList.js @@ -7,23 +7,24 @@ import { AlertIOS, ScrollView } from 'react-native'; -import LoadingSpinner from '../components/LoadingSpinner'; import { GiftedChat } from 'react-native-gifted-chat'; -import GiftedChatSendButton from '../components/3rd_party/GiftedChatSendButton'; -import GiftedChatLoadEarlierButton from '../components/3rd_party/GiftedChatLoadEarlierButton'; -import GiftedChatMessageText from '../components/3rd_party/GiftedChatMessageText'; +import GiftedChatSendButton from '~/common/vendor/components/GiftedChatSendButton'; +import GiftedChatLoadEarlierButton from '~/common/vendor/components/GiftedChatLoadEarlierButton'; +import GiftedChatMessageText from '~/common/vendor/components/GiftedChatMessageText'; +import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import { submit, resetPublish -} from '../actions/message/sendAction'; +} from '~/actions/message/sendAction'; import { fetchPmList, resetPmList, resetPmListResponseStatus -} from '../actions/message/pmListAction'; -import mainStyles from '../styles/components/_Main'; -import styles from '../styles/containers/_PmList'; -import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '../config'; +} from '~/actions/message/pmListAction'; +import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '~/config'; + +import mainStyles from '~/common/styles/Main.style'; +import styles from './PmList.style'; const LOGIN_USER_ID = Symbol(); diff --git a/src/styles/containers/_PmList.js b/src/containers/PmList/PmList.style.js similarity index 87% rename from src/styles/containers/_PmList.js rename to src/containers/PmList/PmList.style.js index a9c6616..13391b5 100644 --- a/src/styles/containers/_PmList.js +++ b/src/containers/PmList/PmList.style.js @@ -1,6 +1,5 @@ import { StyleSheet } from 'react-native'; import Dimensions from 'Dimensions'; -import colors from '../common/_colors'; export default StyleSheet.create({ tickView: { diff --git a/src/containers/Search.js b/src/containers/Search/Search.js similarity index 86% rename from src/containers/Search.js rename to src/containers/Search/Search.js index f493e14..43d3d20 100644 --- a/src/containers/Search.js +++ b/src/containers/Search/Search.js @@ -5,17 +5,18 @@ import { } from 'react-native'; import { connect } from 'react-redux'; import _ from 'lodash'; -import mainStyles from '../styles/components/_Main'; -import indicatorStyles from '../styles/common/_Indicator'; -import TopicList from '../components/TopicList'; -import LoadingSpinner from '../components/LoadingSpinner'; import SearchBar from 'react-native-search-bar'; -import menus from '../constants/menus'; -import { fetchSearch, resetSearch } from '../actions/topic/searchAction'; +import TopicList from '~/components/TopicList/TopicList'; +import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; +import MENUS from '~/constants/menus'; +import { fetchSearch, resetSearch } from '~/actions/topic/searchAction'; + +import mainStyles from '~/common/styles/Main.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; class Search extends Component { static navigationOptions = { - title: menus.search.title + title: MENUS.search.title } constructor(props) { diff --git a/src/styles/containers/_Search.js b/src/containers/Search/Search.style.js similarity index 80% rename from src/styles/containers/_Search.js rename to src/containers/Search/Search.style.js index 5f95509..3c08d97 100644 --- a/src/styles/containers/_Search.js +++ b/src/containers/Search/Search.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ input: { diff --git a/src/containers/Settings.js b/src/containers/Settings/Settings.js similarity index 84% rename from src/containers/Settings.js rename to src/containers/Settings/Settings.js index 4d9b300..4e7c5d7 100644 --- a/src/containers/Settings.js +++ b/src/containers/Settings/Settings.js @@ -10,17 +10,18 @@ import { } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; // import { ImageCache } from "react-native-img-cache"; -import SettingItem from '../components/SettingItem'; -import SettingSwitchItem from '../components/SettingSwitchItem'; -import menus from '../constants/menus'; -import mainStyles from '../styles/components/_Main'; -import styles from '../styles/containers/_Settings'; -import { getSettingsFromStorage, putSettingsToStorage } from '../actions/settingsAction'; -import { resetAlerts } from '../actions/message/alertAction'; +import SettingItem from '~/components/SettingItem/SettingItem'; +import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; +import MENUS from '~/constants/menus'; +import { getSettingsFromStorage, putSettingsToStorage } from '~/actions/settingsAction'; +import { resetAlerts } from '~/actions/message/alertAction'; + +import mainStyles from '~/common/styles/Main.style'; +import styles from '~/containers/Settings/Settings.style'; class Settings extends Component { static navigationOptions = { - title: menus.settings.title + title: MENUS.settings.title } // clearCache() { diff --git a/src/styles/containers/_Settings.js b/src/containers/Settings/Settings.style.js similarity index 88% rename from src/styles/containers/_Settings.js rename to src/containers/Settings/Settings.style.js index 3cda463..2b3913e 100644 --- a/src/styles/containers/_Settings.js +++ b/src/containers/Settings/Settings.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ container: { diff --git a/src/containers/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js similarity index 92% rename from src/containers/TopicDetail.js rename to src/containers/TopicDetail/TopicDetail.js index c700f1e..aebea45 100644 --- a/src/containers/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -11,32 +11,33 @@ import { ActionSheetIOS, Clipboard } from 'react-native'; +import moment from 'moment'; import _ from 'lodash'; -import { NavigationActions } from 'react-navigation'; -import { TOPIC_URL_ROOT } from '../config'; -import Avatar from '../components/Avatar'; import Icon from 'react-native-vector-icons/FontAwesome'; -import moment from 'moment'; -import mainStyles from '../styles/components/_Main'; -import headerRightButtonStyles from '../styles/components/button/_HeaderRightButton'; -import indicatorStyles from '../styles/common/_Indicator'; -import modalStyles from '../styles/common/_Modal'; -import styles from '../styles/containers/_TopicDetail'; -import ReplyModal from '../components/modal/ReplyModal'; -import Comment from '../components/Comment'; -import Content from '../components/Content'; -import VoteList from '../components/VoteList'; -import RewardList from '../components/RewardList'; -import LoadingSpinner from '../components/LoadingSpinner'; -import MessageBar from '../services/MessageBar'; -import SafariView from '../services/SafariView'; -import colors from '../styles/common/_colors'; -import api from '../services/api'; -import { parseContentWithEmoji } from '../utils/contentParser'; +import { NavigationActions } from 'react-navigation'; +import Avatar from '~/components/Avatar/Avatar'; +import ReplyModal from '~/components/ReplyModal/ReplyModal'; +import Comment from '~/components/Comment/Comment'; +import Content from '~/components/Content/Content'; +import VoteList from '~/components/VoteList/VoteList'; +import RewardList from '~/components/RewardList/RewardList'; +import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; +import MessageBar from '~/services/MessageBar'; +import SafariView from '~/services/SafariView'; +import api from '~/services/api'; +import { TOPIC_URL_ROOT } from '~/config'; +import { parseContentWithEmoji } from '~/utils/contentParser'; import { fetchTopic, resetTopic -} from '../actions/topic/topicAction'; +} from '~/actions/topic/topicAction'; + +import mainStyles from '~/common/styles/Main.style'; +import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; +import indicatorStyles from '~/common/styles/Indicator.style'; +import modalStyles from '~/common/styles/Modal.style'; +import colors from '~/common/styles/colors.style'; +import styles from './TopicDetail.style'; const resetAction = NavigationActions.reset({ index: 0, diff --git a/src/styles/containers/_TopicDetail.js b/src/containers/TopicDetail/TopicDetail.style.js similarity index 97% rename from src/styles/containers/_TopicDetail.js rename to src/containers/TopicDetail/TopicDetail.style.js index 544b448..63a00fd 100644 --- a/src/styles/containers/_TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.style.js @@ -1,5 +1,5 @@ import { StyleSheet } from 'react-native'; -import colors from '../common/_colors'; +import colors from '~/common/styles/colors.style'; export default StyleSheet.create({ commentAreaWrapper: { diff --git a/src/containers/WebPage.js b/src/containers/WebPage/WebPage.js similarity index 100% rename from src/containers/WebPage.js rename to src/containers/WebPage/WebPage.js diff --git a/src/package.json b/src/package.json new file mode 100644 index 0000000..7ffbb39 --- /dev/null +++ b/src/package.json @@ -0,0 +1,3 @@ +{ + "name": "~" +} diff --git a/src/reducers/forumList.js b/src/reducers/forumList.js index eab5f59..04a89f8 100644 --- a/src/reducers/forumList.js +++ b/src/reducers/forumList.js @@ -4,8 +4,8 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../actions/forumAction'; -import { REMOVE_CACHE } from '../actions/authorizeAction'; +} from '~/actions/forumAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultState = {}; const defaultForumListState = { diff --git a/src/reducers/message/alert.js b/src/reducers/message/alert.js index 66f4d5d..48a32a4 100644 --- a/src/reducers/message/alert.js +++ b/src/reducers/message/alert.js @@ -4,14 +4,14 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../../actions/message/alertAction'; +} from '~/actions/message/alertAction'; import { MARK_AT_ME_AS_READ, MARK_REPLY_AS_READ, MARK_SYSTEM_AS_READ -} from '../../actions/message/notifyListAction'; -import { MARK_PM_AS_READ } from '../../actions/message/pmSessionListAction'; -import { REMOVE_CACHE } from '../../actions/authorizeAction'; +} from '~/actions/message/notifyListAction'; +import { MARK_PM_AS_READ } from '~/actions/message/pmSessionListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultAlertState = { isFetching: false, diff --git a/src/reducers/message/notifyList.js b/src/reducers/message/notifyList.js index dc0aa2d..edce8fd 100644 --- a/src/reducers/message/notifyList.js +++ b/src/reducers/message/notifyList.js @@ -4,8 +4,8 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../../actions/message/notifyListAction'; -import { REMOVE_CACHE } from '../../actions/authorizeAction'; +} from '~/actions/message/notifyListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultState = {}; const defaultNotifyListState = { diff --git a/src/reducers/message/pmList.js b/src/reducers/message/pmList.js index db42191..ae82651 100644 --- a/src/reducers/message/pmList.js +++ b/src/reducers/message/pmList.js @@ -5,7 +5,7 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../../actions/message/pmListAction'; +} from '~/actions/message/pmListAction'; const defaultPmListState = { isRefreshing: false, diff --git a/src/reducers/message/pmSessionList.js b/src/reducers/message/pmSessionList.js index 0b537cb..6d1e1e0 100644 --- a/src/reducers/message/pmSessionList.js +++ b/src/reducers/message/pmSessionList.js @@ -5,8 +5,8 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../../actions/message/pmSessionListAction'; -import { REMOVE_CACHE } from '../../actions/authorizeAction'; +} from '~/actions/message/pmSessionListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultPmSessionListState = { isRefreshing: false, diff --git a/src/reducers/message/send.js b/src/reducers/message/send.js index 0f53480..86e4212 100644 --- a/src/reducers/message/send.js +++ b/src/reducers/message/send.js @@ -3,7 +3,7 @@ import { REQUEST_COMPELTED, RESET, REQUEST_FAILED -} from '../../actions/message/sendAction'; +} from '~/actions/message/sendAction'; const defaultState = { isPublishing: false, diff --git a/src/reducers/settings.js b/src/reducers/settings.js index 14250a8..5bbd7d4 100644 --- a/src/reducers/settings.js +++ b/src/reducers/settings.js @@ -1,6 +1,6 @@ import { DONE -} from '../actions/settingsAction'; +} from '~/actions/settingsAction'; const defaultSettingsState = { enableNotification: true, diff --git a/src/reducers/topic/search.js b/src/reducers/topic/search.js index 5bbd5b1..7096b00 100644 --- a/src/reducers/topic/search.js +++ b/src/reducers/topic/search.js @@ -3,7 +3,7 @@ import { REQUEST_COMPELTED, REQUEST_FAILED, RESET -} from '../../actions/topic/searchAction'; +} from '~/actions/topic/searchAction'; const defaultSearchState = { // indicate fetching via pull to refresh diff --git a/src/reducers/topic/topicItem.js b/src/reducers/topic/topicItem.js index e4cacd9..66a52f5 100644 --- a/src/reducers/topic/topicItem.js +++ b/src/reducers/topic/topicItem.js @@ -4,7 +4,7 @@ import { REQUEST_COMPELTED, RESET, REQUEST_FAILED -} from '../../actions/topic/topicAction'; +} from '~/actions/topic/topicAction'; // We don't use `cacheManager` to check `shouldFetchTopicItem` in sagas // since topic comments are back with topic details together, and we don't diff --git a/src/reducers/topic/topicList.js b/src/reducers/topic/topicList.js index 92661d9..2a5fa0f 100644 --- a/src/reducers/topic/topicList.js +++ b/src/reducers/topic/topicList.js @@ -5,8 +5,8 @@ import { REQUEST_COMPELTED, RESET, REQUEST_FAILED -} from '../../actions/topic/topicListAction'; -import { REMOVE_CACHE } from '../../actions/authorizeAction'; +} from '~/actions/topic/topicListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultState = {}; const defaultTopicListState = { diff --git a/src/reducers/user.js b/src/reducers/user.js index 67091e8..1acc9a2 100644 --- a/src/reducers/user.js +++ b/src/reducers/user.js @@ -6,7 +6,7 @@ import { REMOVE_CACHE, RESET_AUTHRIZATION, RESET_AUTHRIZATION_RESULT -} from '../actions/authorizeAction'; +} from '~/actions/authorizeAction'; const defaultUserState = { isFetching: false, diff --git a/src/reducers/user/friendList.js b/src/reducers/user/friendList.js index 04d1679..3577d70 100644 --- a/src/reducers/user/friendList.js +++ b/src/reducers/user/friendList.js @@ -3,7 +3,7 @@ import { REQUEST_COMPELTED, REQUEST_FAILED, INVALIDATE -} from '../../actions/user/friendListAction'; +} from '~/actions/user/friendListAction'; const defaultSearchState = { // indicate fetching via pull to refresh diff --git a/src/reducers/user/topicList.js b/src/reducers/user/topicList.js index 4e6fd57..f9108ff 100644 --- a/src/reducers/user/topicList.js +++ b/src/reducers/user/topicList.js @@ -4,8 +4,8 @@ import { REQUEST_STARTED, REQUEST_COMPELTED, REQUEST_FAILED -} from '../../actions/user/topicListAction'; -import { REMOVE_CACHE } from '../../actions/authorizeAction'; +} from '~/actions/user/topicListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; const defaultState = {}; const defaultUserTopicListState = { diff --git a/src/reducers/user/userItem.js b/src/reducers/user/userItem.js index b490f5b..176230c 100644 --- a/src/reducers/user/userItem.js +++ b/src/reducers/user/userItem.js @@ -4,7 +4,7 @@ import { REQUEST_COMPELTED, RESET, REQUEST_FAILED -} from '../../actions/user/userAction'; +} from '~/actions/user/userAction'; const defaultState = {}; const defaultUserState = { diff --git a/src/sagas/index.js b/src/sagas/index.js index 04e4a46..6fd4d14 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,24 +1,24 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; -import * as authorizeActions from '../actions/authorizeAction'; -import * as topicListActions from '../actions/topic/topicListAction'; -import * as userTopicListActions from '../actions/user/topicListAction'; -import * as forumListActions from '../actions/forumAction'; -import * as notifyListActions from '../actions/message/notifyListAction'; -import * as searchActions from '../actions/topic/searchAction'; -import * as topicActions from '../actions/topic/topicAction'; -import * as pmSessionListActions from '../actions/message/pmSessionListAction'; -import * as pmListActions from '../actions/message/pmListAction'; -import * as sendActions from '../actions/message/sendAction'; -import * as alertActions from '../actions/message/alertAction'; -import * as settingsActions from '../actions/settingsAction'; -import * as userActions from '../actions/user/userAction'; -import * as friendListActions from '../actions/user/friendListAction'; - -import cacheManager from '../services/cacheManager'; -import { fetchResource } from '../utils/sagaHelper'; -import api from '../services/api'; +import * as authorizeActions from '~/actions/authorizeAction'; +import * as topicListActions from '~/actions/topic/topicListAction'; +import * as userTopicListActions from '~/actions/user/topicListAction'; +import * as forumListActions from '~/actions/forumAction'; +import * as notifyListActions from '~/actions/message/notifyListAction'; +import * as searchActions from '~/actions/topic/searchAction'; +import * as topicActions from '~/actions/topic/topicAction'; +import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; +import * as pmListActions from '~/actions/message/pmListAction'; +import * as sendActions from '~/actions/message/sendAction'; +import * as alertActions from '~/actions/message/alertAction'; +import * as settingsActions from '~/actions/settingsAction'; +import * as userActions from '~/actions/user/userAction'; +import * as friendListActions from '~/actions/user/friendListAction'; + +import cacheManager from '~/services/cacheManager'; +import { fetchResource } from '~/utils/sagaHelper'; +import api from '~/services/api'; const fetchLoginUserApi = fetchResource.bind(null, authorizeActions, api.fetchLoginUser); const fetchTopicListApi = fetchResource.bind(null, topicListActions, api.fetchTopicList); diff --git a/src/services/ImagePicker.js b/src/services/ImagePicker.js index 4c2720c..e435bf6 100644 --- a/src/services/ImagePicker.js +++ b/src/services/ImagePicker.js @@ -4,7 +4,7 @@ import { ActionSheetIOS } from 'react-native'; import ImagePicker from 'react-native-image-crop-picker'; -import MESSAGES from '../constants/messages' +import MESSAGES from '~/constants/messages'; function takePhoto({ takePhotoOptions, diff --git a/src/services/api.js b/src/services/api.js index ab03143..eed84cd 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -1,6 +1,6 @@ -import request from '../utils/request'; -import { API_ROOT, PLAT_TYPE } from '../config'; -import { getAppHashValue } from '../utils/app'; +import request from '~/utils/request'; +import { getAppHashValue } from '~/utils/app'; +import { API_ROOT, PLAT_TYPE } from '~/config'; const DEFAULT_SORTTYPE = 'all'; const DEFAULT_ORDER = 0; diff --git a/src/store/configureStore.js b/src/store/configureStore.js index ceb6258..27ba6ad 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,6 +1,6 @@ import { createStore, applyMiddleware, compose } from 'redux'; import createSagaMiddleware from 'redux-saga'; -import rootReducer from '../reducers'; +import rootReducer from '~/reducers'; const sagaMiddleware = createSagaMiddleware(); diff --git a/src/utils/app.js b/src/utils/app.js index 2e8dc6b..4016cc0 100644 --- a/src/utils/app.js +++ b/src/utils/app.js @@ -1,5 +1,5 @@ import md5 from 'md5'; -import { APP_AUTH_KEY } from '../config'; +import { APP_AUTH_KEY } from '~/config'; // http://phpjs.org/functions/time/ function time() { diff --git a/src/utils/contentParser.js b/src/utils/contentParser.js index b2d3fc1..401f85a 100644 --- a/src/utils/contentParser.js +++ b/src/utils/contentParser.js @@ -3,8 +3,8 @@ import { Image, StyleSheet } from 'react-native'; -import { DEFAULT_EMOJIS } from '../constants/emojis'; -import { DEFAULT_EMOJI_ROOT } from '../config'; +import { DEFAULT_EMOJIS } from '~/constants/emojis'; +import { DEFAULT_EMOJI_ROOT } from '~/config'; // This method is also used to copy topic content and comment content, // the second parameter here is used to exclude custom emoji as paste diff --git a/src/utils/request.js b/src/utils/request.js index f97f779..eb89c55 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,5 +1,5 @@ import { AsyncStorage } from 'react-native'; -import MessageBar from '../services/MessageBar'; +import MessageBar from '~/services/MessageBar'; function parseJSON(response) { return response.json(); diff --git a/tests/components/Content.test.js b/tests/components/Content.test.js index 775fecb..e3e0f1d 100644 --- a/tests/components/Content.test.js +++ b/tests/components/Content.test.js @@ -1,12 +1,8 @@ import React from 'react'; -import { - View, - Text, - StyleSheet -} from 'react-native'; -import Content from '../../src/components/Content'; +import { Text } from 'react-native'; import { shallow } from 'enzyme'; import { expect } from 'chai'; +import Content from '~/components/Content'; describe('', () => { it('should render child components as many as `content` length', () => { diff --git a/tests/components/TopicList.test.js b/tests/components/TopicList.test.js index 9ad8ad8..cf6c43a 100644 --- a/tests/components/TopicList.test.js +++ b/tests/components/TopicList.test.js @@ -1,7 +1,7 @@ import React from 'react'; -import TopicList from '../../src/components/TopicList'; import { shallow } from 'enzyme'; import { expect } from 'chai'; +import TopicList from '~/components/TopicList'; describe('', () => { it('should not render bad topic data', () => { From 5771f1b643bb9f319d35a2d1ad7dd1dbdbf8780b Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 15:08:47 +0800 Subject: [PATCH 03/58] refactor: introduce ducks pattern for topic list --- index.js | 2 +- src/actions/index.js | 1 - src/actions/topic/topicListAction.js | 16 -- .../modules/topicList/topicList.ducks.js | 163 ++++++++++++++++++ src/components/PublishModal/PublishModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 2 +- src/containers/Home/Home.js | 2 +- src/containers/Menu/Menu.js | 2 +- src/reducers/index.js | 2 +- src/reducers/topic/topicList.js | 150 ---------------- src/sagas/index.js | 4 +- 11 files changed, 171 insertions(+), 175 deletions(-) delete mode 100644 src/actions/topic/topicListAction.js create mode 100644 src/common/modules/topicList/topicList.ducks.js delete mode 100644 src/reducers/topic/topicList.js diff --git a/index.js b/index.js index 1cab52d..d9f4cce 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,6 @@ import 'es6-symbol/implement'; import { AppRegistry } from 'react-native'; -import App from './src/containers/App/App'; +import App from '~/containers/App/App'; AppRegistry.registerComponent('stuhome', () => App); diff --git a/src/actions/index.js b/src/actions/index.js index acc00b0..c417263 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,7 +1,6 @@ export notifyListAction from './message/notifyListAction'; export searchAction from './topic/searchAction'; export topicAction from './topic/topicAction'; -export topicListAction from './topic/topicListAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; export forumAction from './forumAction'; diff --git a/src/actions/topic/topicListAction.js b/src/actions/topic/topicListAction.js deleted file mode 100644 index 5d4d20c..0000000 --- a/src/actions/topic/topicListAction.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const RESET = Symbol(); -export const fetchTopicList = createAction(REQUEST); -export const invalidateTopicList = createAction(INVALIDATE); -export const resetTopicList = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/common/modules/topicList/topicList.ducks.js b/src/common/modules/topicList/topicList.ducks.js new file mode 100644 index 0000000..bdc95bc --- /dev/null +++ b/src/common/modules/topicList/topicList.ducks.js @@ -0,0 +1,163 @@ +import { createAction, handleActions } from 'redux-actions'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import _ from 'lodash'; + +// ********************************* +// Actions +// ********************************* + +export const TOPIC_LIST_FETCH = 'TOPIC_LIST_FETCH'; +export const TOPIC_LIST_INVALIDATE = 'TOPIC_LIST_INVALIDATE'; +export const TOPIC_LIST_RESET = 'TOPIC_LIST_RESET'; + +const TOPIC_LIST_FETCH_REQUEST = 'TOPIC_LIST_FETCH_REQUEST'; +const TOPIC_LIST_FETCH_SUCCESS = 'TOPIC_LIST_FETCH_SUCCESS'; +const TOPIC_LIST_FETCH_FAILURE = 'TOPIC_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchTopicList = createAction(TOPIC_LIST_FETCH); +export const invalidateTopicList = createAction(TOPIC_LIST_INVALIDATE); +export const resetTopicList = createAction(TOPIC_LIST_RESET); + +export const request = createAction(TOPIC_LIST_FETCH_REQUEST); +export const success = createAction(TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); + +// ********************************* +// Reducer +// ********************************* + +const defaultState = {}; +const defaultTopicListState = { + // indicate fetching via pull to refresh + isRefreshing: false, + // indicate fetching via end reached + isEndReached: false, + didInvalidate: false, + boardId: null, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [TOPIC_LIST_INVALIDATE]: (state, action) => { + let { boardId, sortType } = action.payload; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, {}), + [sortType]: { + ..._.get(state, [boardId, sortType], defaultTopicListState), + didInvalidate: true + } + } + }; + }, + [TOPIC_LIST_FETCH_REQUEST]: (state, action) => { + let { boardId, sortType, isEndReached } = action.payload; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, {}), + [sortType]: { + ..._.get(state, [boardId, sortType], defaultTopicListState), + isRefreshing: !isEndReached, + isEndReached: isEndReached, + didInvalidate: false + } + } + }; + }, + [TOPIC_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: topicList, + meta: { + boardId, + sortType + } + } = action; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, {}), + // all topic list of different sort type have same type list + typeList: getMappedTypeList(topicList.classificationType_list), + [sortType]: { + ..._.get(state, [boardId, sortType], defaultTopicListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + boardId, + list: getNewCache(state, topicList.list, boardId, sortType, topicList.page, topicList.rs), + hasMore: !!topicList.has_next, + page: topicList.page, + errCode: topicList.errcode + } + } + }; + }, + [TOPIC_LIST_FETCH_FAILURE]: (state, action) => { + let { boardId, sortType } = action.meta; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, {}), + [sortType]: { + ..._.get(state, [boardId, sortType], defaultTopicListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false + } + } + }; + }, + // In case there is forum or sub forum we have no access. + [TOPIC_LIST_RESET]: (state, action) => { + let { boardId, sortType } = action.payload; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, {}), + [sortType]: { + ..._.get(state, [boardId, sortType], defaultTopicListState), + errCode: '' + } + } + }; + }, + [REMOVE_CACHE]: (state, action) => { debugger; } +}, defaultState); + +// map the fields of `type` to more clear names +function getMappedTypeList(typeList) { + if (!typeList) { return []; } + + return typeList.map((item, index) => { + return { + typeId: item.classificationType_id, + typeName: item.classificationType_name + }; + }); +} + +// cache topic list and return +function getNewCache(oldState, topicList, boardId, sortType, page, isSuccessful) { + // if we have no access to a forum or sub forum, we + // should return original forum groups. + if (!isSuccessful) { return oldState.list; } + + let newTopicList = []; + + if (page !== 1) { + newTopicList = oldState[boardId][sortType].list.concat(topicList); + } else { + newTopicList = topicList; + } + + return newTopicList; +} diff --git a/src/components/PublishModal/PublishModal.js b/src/components/PublishModal/PublishModal.js index db85777..0c9828b 100644 --- a/src/components/PublishModal/PublishModal.js +++ b/src/components/PublishModal/PublishModal.js @@ -24,7 +24,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 6b017f2..feea77f 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -11,7 +11,7 @@ import TopicList from '~/components/TopicList/TopicList'; import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/actions/topic/topicListAction'; +import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/common/modules/topicList/topicList.ducks'; import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index 667aa93..685b46e 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -10,7 +10,7 @@ import Header from '~/components/Header/Header'; import TopicList from '~/components/TopicList/TopicList'; import MenuButton from '~/components/MenuButton/MenuButton'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index 58e88bf..f9e21b9 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -18,7 +18,7 @@ import { resetAuthrizationResult, cleanCache } from '~/actions/authorizeAction'; -import { invalidateTopicList, fetchTopicList } from '~/actions/topic/topicListAction'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import styles from './Menu.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index 72257f6..5957384 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,7 +1,7 @@ import { combineReducers } from 'redux'; import user from './user'; import forumList from './forumList'; -import topicList from './topic/topicList'; +import topicList from '~/common/modules/topicList/topicList.ducks'; import topicItem from './topic/topicItem'; import search from './topic/search'; import notifyList from './message/notifyList'; diff --git a/src/reducers/topic/topicList.js b/src/reducers/topic/topicList.js deleted file mode 100644 index 2a5fa0f..0000000 --- a/src/reducers/topic/topicList.js +++ /dev/null @@ -1,150 +0,0 @@ -import _ from 'lodash'; -import { - INVALIDATE, - REQUEST_STARTED, - REQUEST_COMPELTED, - RESET, - REQUEST_FAILED -} from '~/actions/topic/topicListAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultState = {}; -const defaultTopicListState = { - // indicate fetching via pull to refresh - isRefreshing: false, - // indicate fetching via end reached - isEndReached: false, - didInvalidate: false, - boardId: null, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function topicList(state = defaultState, action) { - switch (action.type) { - case INVALIDATE: { - let { boardId, sortType } = action.payload; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, {}), - [sortType]: { - ..._.get(state, [boardId, sortType], defaultTopicListState), - didInvalidate: true - } - } - }; - } - case REQUEST_STARTED: { - let { boardId, sortType, isEndReached } = action.payload; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, {}), - [sortType]: { - ..._.get(state, [boardId, sortType], defaultTopicListState), - isRefreshing: !isEndReached, - isEndReached: isEndReached, - didInvalidate: false - } - } - }; - } - case REQUEST_COMPELTED: - let { - payload: topicList, - meta: { - boardId, - sortType - } - } = action; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, {}), - // all topic list of different sort type have same type list - typeList: getMappedTypeList(topicList.classificationType_list), - [sortType]: { - ..._.get(state, [boardId, sortType], defaultTopicListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - boardId, - list: getNewCache(state, topicList.list, boardId, sortType, topicList.page, topicList.rs), - hasMore: !!topicList.has_next, - page: topicList.page, - errCode: topicList.errcode - } - } - }; - // in case there is forum or sub forum we have no access - case RESET: { - let { boardId, sortType } = action.payload; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, {}), - [sortType]: { - ..._.get(state, [boardId, sortType], defaultTopicListState), - errCode: '' - } - } - }; - } - case REQUEST_FAILED: { - let { boardId, sortType } = action.meta; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, {}), - [sortType]: { - ..._.get(state, [boardId, sortType], defaultTopicListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false - } - } - }; - } - case REMOVE_CACHE: - return defaultState; - default: - return state; - } -} - -// map the fields of `type` to more clear names -function getMappedTypeList(typeList) { - if (!typeList) { return []; } - - return typeList.map((item, index) => { - return { - typeId: item.classificationType_id, - typeName: item.classificationType_name - }; - }); -} - -// cache topic list and return -function getNewCache(oldState, topicList, boardId, sortType, page, isSuccessful) { - // if we have no access to a forum or sub forum, we - // should return original forum groups. - if (!isSuccessful) { return oldState.list; } - - let newTopicList = []; - - if (page !== 1) { - newTopicList = oldState[boardId][sortType].list.concat(topicList); - } else { - newTopicList = topicList; - } - - return newTopicList; -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 6fd4d14..f36b78a 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,7 +2,7 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as authorizeActions from '~/actions/authorizeAction'; -import * as topicListActions from '~/actions/topic/topicListAction'; +import * as topicListActions from '~/common/modules/topicList/topicList.ducks'; import * as userTopicListActions from '~/actions/user/topicListAction'; import * as forumListActions from '~/actions/forumAction'; import * as notifyListActions from '~/actions/message/notifyListAction'; @@ -101,7 +101,7 @@ function putSettingsToStorage(settings) { function* watchTopicList() { while(true) { - const { payload } = yield take(topicListActions.REQUEST); + const { payload } = yield take(topicListActions.TOPIC_LIST_FETCH); yield fork(fetchTopicList, payload); } } From e562666c0dd2677c9de1254a083450aa9de6073d Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 15:29:55 +0800 Subject: [PATCH 04/58] refactor: introduce ducks pattern for forum list --- src/actions/forumAction.js | 14 --- src/actions/index.js | 1 - .../modules/forumList/forumList.ducks.js | 89 +++++++++++++++++++ .../modules/topicList/topicList.ducks.js | 2 +- .../ForumListModal/ForumListModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 2 +- src/containers/ForumList/ForumList.js | 2 +- src/reducers/forumList.js | 76 ---------------- src/reducers/index.js | 2 +- src/sagas/index.js | 4 +- 10 files changed, 96 insertions(+), 98 deletions(-) delete mode 100644 src/actions/forumAction.js create mode 100644 src/common/modules/forumList/forumList.ducks.js delete mode 100644 src/reducers/forumList.js diff --git a/src/actions/forumAction.js b/src/actions/forumAction.js deleted file mode 100644 index 066832d..0000000 --- a/src/actions/forumAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const fetchForumList = createAction(REQUEST); -export const invalidateForumList = createAction(INVALIDATE); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/actions/index.js b/src/actions/index.js index c417263..1eaeb73 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -3,6 +3,5 @@ export searchAction from './topic/searchAction'; export topicAction from './topic/topicAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; -export forumAction from './forumAction'; export settingsAction from './settingsAction'; export userAction from './user/userAction'; diff --git a/src/common/modules/forumList/forumList.ducks.js b/src/common/modules/forumList/forumList.ducks.js new file mode 100644 index 0000000..8f3e714 --- /dev/null +++ b/src/common/modules/forumList/forumList.ducks.js @@ -0,0 +1,89 @@ +import { createAction, handleActions } from 'redux-actions'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import _ from 'lodash'; + +// ********************************* +// Actions +// ********************************* + +export const FORUM_LIST_FETCH = 'FORUM_LIST_FETCH'; +export const FORUM_LIST_INVALIDATE = 'FORUM_LIST_INVALIDATE'; + +const FORUM_LIST_FETCH_REQUEST = 'FORUM_LIST_FETCH_REQUEST'; +const FORUM_LIST_FETCH_SUCCESS = 'FORUM_LIST_FETCH_SUCCESS'; +const FORUM_LIST_FETCH_FAILURE = 'FORUM_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchForumList = createAction(FORUM_LIST_FETCH); +export const invalidateForumList = createAction(FORUM_LIST_INVALIDATE); + +export const request = createAction(FORUM_LIST_FETCH_REQUEST); +export const success = createAction(FORUM_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(FORUM_LIST_FETCH_FAILURE, null, (...args) => args[1]); + +// ********************************* +// Reducer +// ********************************* + +const defaultState = {}; +const defaultForumListState = { + isRefreshing: false, + didInvalidate: false, + list: [], +}; + +export default handleActions({ + [FORUM_LIST_INVALIDATE]: (state, action) => { + let { boardId } = action.payload; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, defaultForumListState), + didInvalidate: true + } + }; + }, + [FORUM_LIST_FETCH_REQUEST]: (state, action) => { + let { boardId } = action.payload; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, defaultForumListState), + isRefreshing: true, + didInvalidate: false + } + }; + }, + [FORUM_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: forumList, + meta: { + boardId + } + } = action; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, defaultForumListState), + isRefreshing: false, + didInvalidate: false, + list: forumList.list + } + }; + }, + [FORUM_LIST_FETCH_FAILURE]: (state, action) => { + let { boardId } = action.meta; + return { + ...state, + [boardId]: { + ..._.get(state, boardId, defaultForumListState), + isRefreshing: false, + didInvalidate: false + } + }; + }, + [REMOVE_CACHE]: () => defaultState +}, defaultState); diff --git a/src/common/modules/topicList/topicList.ducks.js b/src/common/modules/topicList/topicList.ducks.js index bdc95bc..c8a1c36 100644 --- a/src/common/modules/topicList/topicList.ducks.js +++ b/src/common/modules/topicList/topicList.ducks.js @@ -130,7 +130,7 @@ export default handleActions({ } }; }, - [REMOVE_CACHE]: (state, action) => { debugger; } + [REMOVE_CACHE]: () => defaultState }, defaultState); // map the fields of `type` to more clear names diff --git a/src/components/ForumListModal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js index defdbc8..c4714c8 100644 --- a/src/components/ForumListModal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import Header from '~/components/Header/Header'; -import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index feea77f..3f11b50 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -12,7 +12,7 @@ import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/common/modules/topicList/topicList.ducks'; -import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index 312720d..fdbbeac 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -8,7 +8,7 @@ import { import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import MENUS from '~/constants/menus'; -import { invalidateForumList, fetchForumList } from '~/actions/forumAction'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/reducers/forumList.js b/src/reducers/forumList.js deleted file mode 100644 index 04a89f8..0000000 --- a/src/reducers/forumList.js +++ /dev/null @@ -1,76 +0,0 @@ -import _ from 'lodash'; -import { - INVALIDATE, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/forumAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultState = {}; -const defaultForumListState = { - isRefreshing: false, - didInvalidate: false, - list: [], -}; - -export default function forumList(state = defaultState, action) { - switch (action.type) { - case INVALIDATE: { - let { boardId } = action.payload; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, defaultForumListState), - didInvalidate: true - } - }; - } - case REQUEST_STARTED: { - let { boardId } = action.payload; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, defaultForumListState), - isRefreshing: true, - didInvalidate: false - } - }; - } - case REQUEST_COMPELTED: - let { - payload: forumList, - meta: { - boardId - } - } = action; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, defaultForumListState), - isRefreshing: false, - didInvalidate: false, - list: forumList.list - } - }; - case REQUEST_FAILED: { - let { boardId } = action.meta; - - return { - ...state, - [boardId]: { - ..._.get(state, boardId, defaultForumListState), - isRefreshing: false, - didInvalidate: false - } - }; - } - case REMOVE_CACHE: - return defaultState; - default: - return state; - } -} diff --git a/src/reducers/index.js b/src/reducers/index.js index 5957384..7220f6e 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,6 +1,6 @@ import { combineReducers } from 'redux'; import user from './user'; -import forumList from './forumList'; +import forumList from '~/common/modules/forumList/forumList.ducks'; import topicList from '~/common/modules/topicList/topicList.ducks'; import topicItem from './topic/topicItem'; import search from './topic/search'; diff --git a/src/sagas/index.js b/src/sagas/index.js index f36b78a..326af81 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -4,7 +4,7 @@ import { take, fork, select, put, call } from 'redux-saga/effects'; import * as authorizeActions from '~/actions/authorizeAction'; import * as topicListActions from '~/common/modules/topicList/topicList.ducks'; import * as userTopicListActions from '~/actions/user/topicListAction'; -import * as forumListActions from '~/actions/forumAction'; +import * as forumListActions from '~/common/modules/forumList/forumList.ducks'; import * as notifyListActions from '~/actions/message/notifyListAction'; import * as searchActions from '~/actions/topic/searchAction'; import * as topicActions from '~/actions/topic/topicAction'; @@ -137,7 +137,7 @@ function* fetchUserTopicList(payload) { function* watchForumList() { while(true) { - const { payload } = yield take(forumListActions.REQUEST); + const { payload } = yield take(forumListActions.FORUM_LIST_FETCH); yield fork(fetchForumList, payload); } } From 5ce174638afb016c915038064382c88b8ed885a9 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 16:34:18 +0800 Subject: [PATCH 05/58] refactor: introduce ducks patter for settings --- src/actions/index.js | 1 - src/actions/settingsAction.js | 10 ------ src/common/modules/settings/settings.ducks.js | 33 +++++++++++++++++++ src/containers/Navigator/Navigator.js | 6 ++-- src/containers/Settings/Settings.js | 10 +++--- src/reducers/index.js | 2 +- src/reducers/settings.js | 20 ----------- src/sagas/index.js | 20 +++++------ 8 files changed, 52 insertions(+), 50 deletions(-) delete mode 100644 src/actions/settingsAction.js create mode 100644 src/common/modules/settings/settings.ducks.js delete mode 100644 src/reducers/settings.js diff --git a/src/actions/index.js b/src/actions/index.js index 1eaeb73..aa88590 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -3,5 +3,4 @@ export searchAction from './topic/searchAction'; export topicAction from './topic/topicAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; -export settingsAction from './settingsAction'; export userAction from './user/userAction'; diff --git a/src/actions/settingsAction.js b/src/actions/settingsAction.js deleted file mode 100644 index a7da670..0000000 --- a/src/actions/settingsAction.js +++ /dev/null @@ -1,10 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const RETRIEVE = Symbol(); -export const getSettingsFromStorage = createAction(RETRIEVE); - -export const STORE = Symbol(); -export const putSettingsToStorage = createAction(STORE); - -export const DONE = Symbol(); -export const done = createAction(DONE); diff --git a/src/common/modules/settings/settings.ducks.js b/src/common/modules/settings/settings.ducks.js new file mode 100644 index 0000000..ea0fef6 --- /dev/null +++ b/src/common/modules/settings/settings.ducks.js @@ -0,0 +1,33 @@ +import { createAction, handleActions } from 'redux-actions'; + +// ********************************* +// Actions +// ********************************* + +export const SETTINGS_RETRIEVE = 'SETTINGS_RETRIEVE'; +export const SETTINGS_STORE = 'SETTINGS_STORE'; +export const SETTINGS_STORE_DONE = 'SETTINGS_STORE_DONE'; + +// ********************************* +// Action Creators +// ********************************* + +export const retrieveSettingsFromStorage = createAction(SETTINGS_RETRIEVE); +export const storeSettingsToStorage = createAction(SETTINGS_STORE); +export const storeSettingsToRedux = createAction(SETTINGS_STORE_DONE); + +// ********************************* +// Reducer +// ********************************* + +const defaultSettingsState = { + enableNotification: true, + enablePublishDialog: false +}; + +export default handleActions({ + [SETTINGS_STORE_DONE]: (state, action) => ({ + ...state, + ...action.payload + }) +}, defaultSettingsState); diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index fc296f7..e192ad2 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -22,7 +22,7 @@ import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; import { getUserFromStorage } from '~/actions/authorizeAction'; -import { getSettingsFromStorage } from '~/actions/settingsAction'; +import { retrieveSettingsFromStorage } from '~/common/modules/settings/settings.ducks'; import { fetchAlerts } from '~/actions/message/alertAction'; import { ALERT_POLL_FREQUENCY } from '~/config'; @@ -132,7 +132,7 @@ class AppRoot extends Component { MessageBarManager.registerMessageBar(this.refs.alert); this.props.getUserFromStorage(); - this.props.getSettingsFromStorage(); + this.props.retrieveSettingsFromStorage(); } componentWillReceiveProps(nextProps) { @@ -187,6 +187,6 @@ function mapStateToProps({ user, settings }) { export default connect(mapStateToProps, { getUserFromStorage, - getSettingsFromStorage, + retrieveSettingsFromStorage, fetchAlerts })(AppRoot); diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 4e7c5d7..38b4269 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -13,7 +13,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; -import { getSettingsFromStorage, putSettingsToStorage } from '~/actions/settingsAction'; +import { retrieveSettingsFromStorage, storeSettingsToStorage } from '~/common/modules/settings/settings.ducks'; import { resetAlerts } from '~/actions/message/alertAction'; import mainStyles from '~/common/styles/Main.style'; @@ -38,13 +38,13 @@ class Settings extends Component { // } handleNotificationValueChange(value) { - this.props.putSettingsToStorage({ enableNotification: value }); + this.props.storeSettingsToStorage({ enableNotification: value }); // Clear message alters. this.props.resetAlerts(); } handlePublishDialogValueChange(value) { - this.props.putSettingsToStorage({ enablePublishDialog: value }); + this.props.storeSettingsToStorage({ enablePublishDialog: value }); } render() { @@ -89,7 +89,7 @@ function mapStateToProps({ settings }) { } export default connect(mapStateToProps, { - getSettingsFromStorage, - putSettingsToStorage, + retrieveSettingsFromStorage, + storeSettingsToStorage, resetAlerts })(Settings); diff --git a/src/reducers/index.js b/src/reducers/index.js index 7220f6e..cbe7563 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -10,7 +10,7 @@ import userTopicList from './user/topicList'; import pmList from './message/pmList'; import send from './message/send'; import alert from './message/alert'; -import settings from './settings'; +import settings from '~/common/modules/settings/settings.ducks'; import userItem from './user/userItem'; import friendList from './user/friendList'; diff --git a/src/reducers/settings.js b/src/reducers/settings.js deleted file mode 100644 index 5bbd7d4..0000000 --- a/src/reducers/settings.js +++ /dev/null @@ -1,20 +0,0 @@ -import { - DONE -} from '~/actions/settingsAction'; - -const defaultSettingsState = { - enableNotification: true, - enablePublishDialog: false -}; - -export default function settings(state = defaultSettingsState, action) { - switch (action.type) { - case DONE: - return { - ...state, - ...action.payload - }; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 326af81..c7df441 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -12,7 +12,7 @@ import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; import * as pmListActions from '~/actions/message/pmListAction'; import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/actions/message/alertAction'; -import * as settingsActions from '~/actions/settingsAction'; +import * as settingsActions from '~/common/modules/settings/settings.ducks'; import * as userActions from '~/actions/user/userAction'; import * as friendListActions from '~/actions/user/friendListAction'; @@ -65,35 +65,35 @@ function* watchLogin() { function* watchRetrieveSettings() { while(true) { - yield take(settingsActions.RETRIEVE); - let settings = yield call(getSettingsFromStorage); + yield take(settingsActions.SETTINGS_RETRIEVE); + let settings = yield call(retrieveSettingsFromStorage); if (settings) { settings = JSON.parse(settings); - yield put(settingsActions.done(settings)); + yield put(settingsActions.storeSettingsToRedux(settings)); } } } -function getSettingsFromStorage() { +function retrieveSettingsFromStorage() { return new Promise(resolve => AsyncStorage.getItem('settings').then(resolve)); } function* watchStoreSettings() { while(true) { - const { payload } = yield take(settingsActions.STORE); + const { payload } = yield take(settingsActions.SETTINGS_STORE); // get old settings - let settings = yield call(getSettingsFromStorage); + let settings = yield call(retrieveSettingsFromStorage); // merge with new settings let newSettings = Object.assign({}, JSON.parse(settings), payload); // store new settings in storage - yield call(putSettingsToStorage, JSON.stringify(newSettings)); + yield call(storeSettingsToStorage, JSON.stringify(newSettings)); // update redux store - yield put(settingsActions.done(newSettings)); + yield put(settingsActions.storeSettingsToRedux(newSettings)); } } -function putSettingsToStorage(settings) { +function storeSettingsToStorage(settings) { return new Promise(resolve => AsyncStorage.setItem('settings', settings).then(resolve)); } From 66b5e3404d5de6669af45f18b154234baf823d00 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 17:01:30 +0800 Subject: [PATCH 06/58] refactor: rename module name then we can put more similar ducks together --- src/common/modules/{forumList => forum}/forumList.ducks.js | 0 src/common/modules/{topicList => topic}/topicList.ducks.js | 0 src/components/ForumListModal/ForumListModal.js | 2 +- src/components/PublishModal/PublishModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 4 ++-- src/containers/ForumList/ForumList.js | 2 +- src/containers/Home/Home.js | 2 +- src/containers/Menu/Menu.js | 2 +- src/reducers/index.js | 4 ++-- src/sagas/index.js | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) rename src/common/modules/{forumList => forum}/forumList.ducks.js (100%) rename src/common/modules/{topicList => topic}/topicList.ducks.js (100%) diff --git a/src/common/modules/forumList/forumList.ducks.js b/src/common/modules/forum/forumList.ducks.js similarity index 100% rename from src/common/modules/forumList/forumList.ducks.js rename to src/common/modules/forum/forumList.ducks.js diff --git a/src/common/modules/topicList/topicList.ducks.js b/src/common/modules/topic/topicList.ducks.js similarity index 100% rename from src/common/modules/topicList/topicList.ducks.js rename to src/common/modules/topic/topicList.ducks.js diff --git a/src/components/ForumListModal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js index c4714c8..dd02f9d 100644 --- a/src/components/ForumListModal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import Header from '~/components/Header/Header'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/components/PublishModal/PublishModal.js b/src/components/PublishModal/PublishModal.js index 0c9828b..8d8def8 100644 --- a/src/components/PublishModal/PublishModal.js +++ b/src/components/PublishModal/PublishModal.js @@ -24,7 +24,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 3f11b50..d1490b6 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -11,8 +11,8 @@ import TopicList from '~/components/TopicList/TopicList'; import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/common/modules/topicList/topicList.ducks'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; +import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/common/modules/topic/topicList.ducks'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index fdbbeac..5257d6c 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -8,7 +8,7 @@ import { import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import MENUS from '~/constants/menus'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forumList/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index 685b46e..ca84019 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -10,7 +10,7 @@ import Header from '~/components/Header/Header'; import TopicList from '~/components/TopicList/TopicList'; import MenuButton from '~/components/MenuButton/MenuButton'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index f9e21b9..c777f4b 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -18,7 +18,7 @@ import { resetAuthrizationResult, cleanCache } from '~/actions/authorizeAction'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topicList/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import styles from './Menu.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index cbe7563..8aefba9 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,7 +1,7 @@ import { combineReducers } from 'redux'; import user from './user'; -import forumList from '~/common/modules/forumList/forumList.ducks'; -import topicList from '~/common/modules/topicList/topicList.ducks'; +import forumList from '~/common/modules/forum/forumList.ducks'; +import topicList from '~/common/modules/topic/topicList.ducks'; import topicItem from './topic/topicItem'; import search from './topic/search'; import notifyList from './message/notifyList'; diff --git a/src/sagas/index.js b/src/sagas/index.js index c7df441..0f09bc1 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,9 +2,9 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as authorizeActions from '~/actions/authorizeAction'; -import * as topicListActions from '~/common/modules/topicList/topicList.ducks'; +import * as topicListActions from '~/common/modules/topic/topicList.ducks'; import * as userTopicListActions from '~/actions/user/topicListAction'; -import * as forumListActions from '~/common/modules/forumList/forumList.ducks'; +import * as forumListActions from '~/common/modules/forum/forumList.ducks'; import * as notifyListActions from '~/actions/message/notifyListAction'; import * as searchActions from '~/actions/topic/searchAction'; import * as topicActions from '~/actions/topic/topicAction'; From 1581e02b1b290a7e70a45f1c2d7f33ecf968e6bd Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 17:20:17 +0800 Subject: [PATCH 07/58] refactor: introduce ducks pattern for search list --- src/actions/index.js | 1 - src/actions/topic/searchAction.js | 14 ---- src/common/modules/topic/searchList.ducks.js | 75 ++++++++++++++++++++ src/containers/Search/Search.js | 30 ++++---- src/reducers/index.js | 4 +- src/reducers/topic/search.js | 62 ---------------- src/sagas/index.js | 6 +- 7 files changed, 95 insertions(+), 97 deletions(-) delete mode 100644 src/actions/topic/searchAction.js create mode 100644 src/common/modules/topic/searchList.ducks.js delete mode 100644 src/reducers/topic/search.js diff --git a/src/actions/index.js b/src/actions/index.js index aa88590..096e614 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,5 +1,4 @@ export notifyListAction from './message/notifyListAction'; -export searchAction from './topic/searchAction'; export topicAction from './topic/topicAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; diff --git a/src/actions/topic/searchAction.js b/src/actions/topic/searchAction.js deleted file mode 100644 index fedf882..0000000 --- a/src/actions/topic/searchAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const fetchSearch = createAction(REQUEST); -export const resetSearch = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/common/modules/topic/searchList.ducks.js b/src/common/modules/topic/searchList.ducks.js new file mode 100644 index 0000000..8dc2cf6 --- /dev/null +++ b/src/common/modules/topic/searchList.ducks.js @@ -0,0 +1,75 @@ +import { createAction, handleActions } from 'redux-actions'; + +// ********************************* +// Actions +// ********************************* + +export const SEARCH_LIST_FETCH = 'SEARCH_LIST_FETCH'; +export const SEARCH_LIST_RESET = 'SEARCH_LIST_RESET'; + +const SEARCH_LIST_FETCH_REQUEST = 'SEARCH_LIST_FETCH_REQUEST'; +const SEARCH_LIST_FETCH_SUCCESS = 'SEARCH_LIST_FETCH_SUCCESS'; +const SEARCH_LIST_FETCH_FAILURE = 'SEARCH_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchSearchList = createAction(SEARCH_LIST_FETCH); +export const resetSearchList = createAction(SEARCH_LIST_RESET); + +export const request = createAction(SEARCH_LIST_FETCH_REQUEST); +export const success = createAction(SEARCH_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(SEARCH_LIST_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultSearchListState = { + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [SEARCH_LIST_FETCH_REQUEST]: (state, action) => ({ + ...state, + isRefreshing: !action.payload.isEndReached, + isEndReached: action.payload.isEndReached, + didInvalidate: false + }), + [SEARCH_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: topicList + } = action; + + // If there is no search result, both `page` + // and `list` will return `undefined`. + if (topicList.page !== 1 && topicList.list) { + topicList.list = state.list.concat(topicList.list); + } + + return { + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: topicList.list || [], + hasMore: !!topicList.has_next, + page: topicList.page, + errCode: topicList.errcode + }; + }, + [SEARCH_LIST_FETCH_FAILURE]: (state, action) => ({ + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false + }), + [SEARCH_LIST_RESET]: () => defaultSearchListState +}, defaultSearchListState); diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 43d3d20..0faff0a 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -9,7 +9,7 @@ import SearchBar from 'react-native-search-bar'; import TopicList from '~/components/TopicList/TopicList'; import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import MENUS from '~/constants/menus'; -import { fetchSearch, resetSearch } from '~/actions/topic/searchAction'; +import { fetchSearchList, resetSearchList } from '~/common/modules/topic/searchList.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; @@ -33,15 +33,15 @@ class Search extends Component { } componentWillUnmount() { - this.props.resetSearch(); + this.props.resetSearchList(); } componentWillReceiveProps(nextProps) { - let { search } = nextProps; - if (search.errCode) { - AlertIOS.alert('提示', search.errCode); + let { searchList } = nextProps; + if (searchList.errCode) { + AlertIOS.alert('提示', searchList.errCode); // Clean error message. - this.props.resetSearch(); + this.props.resetSearchList(); } } @@ -57,7 +57,7 @@ class Search extends Component { // Search topic list can not be pulled to refresh, // so there is no need to invalidate topic list here, // this method is only used for end reach refreshing. - this.props.fetchSearch({ + this.props.fetchSearchList({ keyword: this.state.keyword, isEndReached, sortType: 'all', @@ -77,7 +77,7 @@ class Search extends Component { render() { let { navigation, - search, + searchList, userId } = this.props; @@ -86,13 +86,13 @@ class Search extends Component { this.setState({ focus: true })} onChangeText={keyword => this.handleChange(keyword)} onSearchButtonPress={() => this.handleSearch()} onCancelButtonPress={() => this.getSearchBarBlur()} /> - {search.isRefreshing && ( + {searchList.isRefreshing && ( ) || ( )} @@ -108,14 +108,14 @@ class Search extends Component { } } -function mapStateToProps({ search, user }) { +function mapStateToProps({ searchList, user }) { return { userId: _.get(user, ['authrization', 'uid']), - search + searchList }; } export default connect(mapStateToProps, { - fetchSearch, - resetSearch + fetchSearchList, + resetSearchList })(Search); diff --git a/src/reducers/index.js b/src/reducers/index.js index 8aefba9..d753184 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -3,7 +3,7 @@ import user from './user'; import forumList from '~/common/modules/forum/forumList.ducks'; import topicList from '~/common/modules/topic/topicList.ducks'; import topicItem from './topic/topicItem'; -import search from './topic/search'; +import searchList from '~/common/modules/topic/searchList.ducks'; import notifyList from './message/notifyList'; import pmSessionList from './message/pmSessionList'; import userTopicList from './user/topicList'; @@ -26,7 +26,7 @@ export default combineReducers({ user, userItem, topicItem, - search, + searchList, friendList, userTopicList, diff --git a/src/reducers/topic/search.js b/src/reducers/topic/search.js deleted file mode 100644 index 7096b00..0000000 --- a/src/reducers/topic/search.js +++ /dev/null @@ -1,62 +0,0 @@ -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED, - RESET -} from '~/actions/topic/searchAction'; - -const defaultSearchState = { - // indicate fetching via pull to refresh - isRefreshing: false, - // indicate fetching via end reached - isEndReached: false, - didInvalidate: false, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function search(state = defaultSearchState, action) { - switch (action.type) { - case REQUEST_STARTED: - return { - ...state, - isRefreshing: !action.payload.isEndReached, - isEndReached: action.payload.isEndReached, - didInvalidate: false - }; - case REQUEST_COMPELTED: - let { - payload: topicList - } = action; - - // if there is no search result, both `page` - // and `list` will return `undefined`. - if (topicList.page !== 1 && topicList.list) { - topicList.list = state.list.concat(topicList.list); - } - - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: topicList.list || [], - hasMore: !!topicList.has_next, - page: topicList.page, - errCode: topicList.errcode - }; - case REQUEST_FAILED: - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false - }; - case RESET: - return defaultSearchState; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 0f09bc1..ba8b54c 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -6,7 +6,7 @@ import * as topicListActions from '~/common/modules/topic/topicList.ducks'; import * as userTopicListActions from '~/actions/user/topicListAction'; import * as forumListActions from '~/common/modules/forum/forumList.ducks'; import * as notifyListActions from '~/actions/message/notifyListAction'; -import * as searchActions from '~/actions/topic/searchAction'; +import * as searchListActions from '~/common/modules/topic/searchList.ducks'; import * as topicActions from '~/actions/topic/topicAction'; import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; import * as pmListActions from '~/actions/message/pmListAction'; @@ -25,7 +25,7 @@ const fetchTopicListApi = fetchResource.bind(null, topicListActions, api.fetchTo const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchForumListApi = fetchResource.bind(null, forumListActions, api.fetchForumList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); -const fetchSearchListApi = fetchResource.bind(null, searchActions, api.fetchSearchList); +const fetchSearchListApi = fetchResource.bind(null, searchListActions, api.fetchSearchList); const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); @@ -173,7 +173,7 @@ function* fetchNotifyList(payload) { function* watchSearchList() { while(true) { - const { payload } = yield take(searchActions.REQUEST); + const { payload } = yield take(searchListActions.SEARCH_LIST_FETCH); yield fork(fetchSearchListApi, payload); } } From daa0c27958bffecce044abb1f86004fc18a4ed4f Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 17:37:44 +0800 Subject: [PATCH 08/58] refactor: introduce ducks pattern for topic --- src/actions/index.js | 1 - src/actions/topic/topicAction.js | 14 --- src/common/modules/topic/topic.ducks.js | 126 ++++++++++++++++++++++ src/components/ReplyModal/ReplyModal.js | 2 +- src/containers/TopicDetail/TopicDetail.js | 5 +- src/reducers/index.js | 2 +- src/reducers/topic/topicItem.js | 112 ------------------- src/sagas/index.js | 4 +- 8 files changed, 131 insertions(+), 135 deletions(-) delete mode 100644 src/actions/topic/topicAction.js create mode 100644 src/common/modules/topic/topic.ducks.js delete mode 100644 src/reducers/topic/topicItem.js diff --git a/src/actions/index.js b/src/actions/index.js index 096e614..277e20c 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,5 +1,4 @@ export notifyListAction from './message/notifyListAction'; -export topicAction from './topic/topicAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; export userAction from './user/userAction'; diff --git a/src/actions/topic/topicAction.js b/src/actions/topic/topicAction.js deleted file mode 100644 index 2118baa..0000000 --- a/src/actions/topic/topicAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const fetchTopic = createAction(REQUEST); -export const resetTopic = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/common/modules/topic/topic.ducks.js b/src/common/modules/topic/topic.ducks.js new file mode 100644 index 0000000..661af4b --- /dev/null +++ b/src/common/modules/topic/topic.ducks.js @@ -0,0 +1,126 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; + +// ********************************* +// Actions +// ********************************* + +export const TOPIC_FETCH = 'TOPIC_FETCH'; +export const TOPIC_RESET = 'TOPIC_RESET'; + +const TOPIC_FETCH_REQUEST = 'TOPIC_FETCH_REQUEST'; +const TOPIC_FETCH_SUCCESS = 'TOPIC_FETCH_SUCCESS'; +const TOPIC_FETCH_FAILURE = 'TOPIC_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchTopic = createAction(TOPIC_FETCH); +export const resetTopic = createAction(TOPIC_RESET); + +export const request = createAction(TOPIC_FETCH_REQUEST); +export const success = createAction(TOPIC_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(TOPIC_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +// We don't use `cacheManager` to check `shouldFetchTopicItem` in sagas +// since topic comments are back with topic details together, and we don't +// want to cache comments (that said we will always get latest comments with +// latest topic information in `componentDidMount` every time). +// +// In this way, we should not also reset/clear the topic item in `componentWillUnmount`. +// Say we navigate from topic A --> topic B --> topic A, then touch back twice to topic +// A. We will get blank page since the content of topic A has been `reset` in the third +// page's `componentWillUnmount`. +// +// The only disadvantage of not resetting topic item is that, if we navigate from +// topic A --> topic A (try it out in http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1705815), +// we will see the content of first topic A will replace with loading spinner since we trigger +// request action for topic A again. As tradeoff, I think it's not big deal. + +// There is no race condition if we isolate every topic item via topicId in redux store. +// https://github.com/just4fun/stuhome/issues/25 + +const defaultState = {}; +const defaultTopicState = { + isFetching: false, + isEndReached: false, + topic: null, + // Comment list. + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [TOPIC_FETCH_REQUEST]: (state, action) => { + let { topicId, isEndReached } = action.payload; + return { + ...state, + [topicId]: { + ..._.get(state, topicId, defaultTopicState), + isFetching: !isEndReached, + isEndReached: isEndReached + } + }; + }, + [TOPIC_FETCH_SUCCESS]: (state, action) => { + let { + payload: { + page, + list, + topic, + has_next, + errcode, + }, + meta: { + topicId + } + } = action; + + if (!errcode && page !== 1) { + list = _.get(state, [topicId, 'list'], []).concat(list); + // the API won't return `topic` field when `page` is not equal `1` + topic = _.get(state, [topicId, 'topic'], {}); + } + + return { + ...state, + [topicId]: { + ..._.get(state, topicId, defaultTopicState), + isFetching: false, + isEndReached: false, + topic: topic, + list: list, + hasMore: !!has_next, + page: page, + errCode: errcode + } + }; + }, + [TOPIC_FETCH_FAILURE]: (state, action) => { + let { topicId } = action.payload; + return { + ...state, + [topicId]: { + ..._.get(state, topicId, defaultTopicState), + isFetching: false, + isEndReached: false + } + }; + }, + // We didn't cahce topic item like topic list, because comment list + // will be returned with topic info together, that means we will also + // cache topic comments as well. + // + // This will be triggerd in `componentWillUnmount()`. + [TOPIC_RESET]: (state, action) => { + let { topicId } = action.payload; + return _.pickBy(state, (value, key) => +key !== +topicId); + } +}, defaultTopicState); diff --git a/src/components/ReplyModal/ReplyModal.js b/src/components/ReplyModal/ReplyModal.js index 6eeda79..fd2ac94 100644 --- a/src/components/ReplyModal/ReplyModal.js +++ b/src/components/ReplyModal/ReplyModal.js @@ -19,7 +19,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { fetchTopic } from '~/actions/topic/topicAction'; +import { fetchTopic } from '~/common/modules/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index aebea45..3478d0a 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -27,10 +27,7 @@ import SafariView from '~/services/SafariView'; import api from '~/services/api'; import { TOPIC_URL_ROOT } from '~/config'; import { parseContentWithEmoji } from '~/utils/contentParser'; -import { - fetchTopic, - resetTopic -} from '~/actions/topic/topicAction'; +import { fetchTopic, resetTopic } from '~/common/modules/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index d753184..ba1f6d6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -2,7 +2,7 @@ import { combineReducers } from 'redux'; import user from './user'; import forumList from '~/common/modules/forum/forumList.ducks'; import topicList from '~/common/modules/topic/topicList.ducks'; -import topicItem from './topic/topicItem'; +import topicItem from '~/common/modules/topic/topic.ducks'; import searchList from '~/common/modules/topic/searchList.ducks'; import notifyList from './message/notifyList'; import pmSessionList from './message/pmSessionList'; diff --git a/src/reducers/topic/topicItem.js b/src/reducers/topic/topicItem.js deleted file mode 100644 index 66a52f5..0000000 --- a/src/reducers/topic/topicItem.js +++ /dev/null @@ -1,112 +0,0 @@ -import _ from 'lodash'; -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - RESET, - REQUEST_FAILED -} from '~/actions/topic/topicAction'; - -// We don't use `cacheManager` to check `shouldFetchTopicItem` in sagas -// since topic comments are back with topic details together, and we don't -// want to cache comments (that said we will always get latest comments with -// latest topic information in `componentDidMount` every time). -// -// In this way, we should not also reset/clear the topic item in `componentWillUnmount`. -// Say we navigate from topic A --> topic B --> topic A, then touch back twice to topic -// A. We will get blank page since the content of topic A has been `reset` in the third -// page's `componentWillUnmount`. -// -// The only disadvantage of not resetting topic item is that, if we navigate from -// topic A --> topic A (try it out in http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1705815), -// we will see the content of first topic A will replace with loading spinner since we trigger -// request action for topic A again. As tradeoff, I think it's not big deal. - -// There is no race condition if we isolate every topic item via topicId in redux store. -// https://github.com/just4fun/stuhome/issues/25 -const defaultState = {}; -const defaultTopicState = { - isFetching: false, - // indicate fetching via end reached - isEndReached: false, - topic: null, - // comment list - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function topicItem(state = defaultState, action) { - switch (action.type) { - case REQUEST_STARTED: { - let { topicId, isEndReached } = action.payload; - - return { - ...state, - [topicId]: { - ..._.get(state, topicId, defaultTopicState), - isFetching: !isEndReached, - isEndReached: isEndReached - } - }; - } - case REQUEST_COMPELTED: { - let { - payload: { - page, - list, - topic, - has_next, - errcode, - }, - meta: { - topicId - } - } = action; - - if (!errcode && page !== 1) { - list = _.get(state, [topicId, 'list'], []).concat(list); - // the API won't return `topic` field when `page` is not equal `1` - topic = _.get(state, [topicId, 'topic'], {}); - } - - return { - ...state, - [topicId]: { - ..._.get(state, topicId, defaultTopicState), - isFetching: false, - isEndReached: false, - topic: topic, - list: list, - hasMore: !!has_next, - page: page, - errCode: errcode - } - }; - } - // We didn't cahce topic item like topic list, because comment list - // will be returned with topic info together, that means we will also - // cache topic comments as well. - // - // This will be triggerd in `componentWillUnmount()`. - case RESET: { - let { topicId } = action.payload; - - return _.pickBy(state, (value, key) => +key !== +topicId); - } - case REQUEST_FAILED: { - let { topicId } = action.payload; - - return { - ...state, - [topicId]: { - ..._.get(state, topicId, defaultTopicState), - isFetching: false, - isEndReached: false - } - }; - } - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index ba8b54c..9b463e7 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -7,7 +7,7 @@ import * as userTopicListActions from '~/actions/user/topicListAction'; import * as forumListActions from '~/common/modules/forum/forumList.ducks'; import * as notifyListActions from '~/actions/message/notifyListAction'; import * as searchListActions from '~/common/modules/topic/searchList.ducks'; -import * as topicActions from '~/actions/topic/topicAction'; +import * as topicActions from '~/common/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; import * as pmListActions from '~/actions/message/pmListAction'; import * as sendActions from '~/actions/message/sendAction'; @@ -182,7 +182,7 @@ function* watchSearchList() { function* watchTopic() { while(true) { - const { payload } = yield take(topicActions.REQUEST); + const { payload } = yield take(topicActions.TOPIC_FETCH); yield fork(fetchTopicApi, payload); } } From 3cffcb70d49407f3187bab7bb984d513d4001b96 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sat, 11 Aug 2018 21:35:20 +0800 Subject: [PATCH 09/58] refactor: introduce ducks pattern for alert --- src/actions/message/alertAction.js | 14 ---- src/common/modules/message/alert.ducks.js | 94 +++++++++++++++++++++++ src/containers/Navigator/Navigator.js | 10 +-- src/containers/Settings/Settings.js | 6 +- src/reducers/index.js | 2 +- src/reducers/message/alert.js | 89 --------------------- src/sagas/index.js | 8 +- src/services/api.js | 2 +- 8 files changed, 108 insertions(+), 117 deletions(-) delete mode 100644 src/actions/message/alertAction.js create mode 100644 src/common/modules/message/alert.ducks.js delete mode 100644 src/reducers/message/alert.js diff --git a/src/actions/message/alertAction.js b/src/actions/message/alertAction.js deleted file mode 100644 index 7511d6e..0000000 --- a/src/actions/message/alertAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const fetchAlerts = createAction(REQUEST); -export const resetAlerts = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/common/modules/message/alert.ducks.js b/src/common/modules/message/alert.ducks.js new file mode 100644 index 0000000..1b5d758 --- /dev/null +++ b/src/common/modules/message/alert.ducks.js @@ -0,0 +1,94 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; +import { + MARK_AT_ME_AS_READ, + MARK_REPLY_AS_READ, + MARK_SYSTEM_AS_READ +} from '~/actions/message/notifyListAction'; +import { MARK_PM_AS_READ } from '~/actions/message/pmSessionListAction'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; + +// ********************************* +// Actions +// ********************************* + +export const ALERT_FETCH = 'ALERT_FETCH'; +export const ALERT_RESET = 'ALERT_RESET'; + +const ALERT_FETCH_REQUEST = 'ALERT_FETCH_REQUEST'; +const ALERT_FETCH_SUCCESS = 'ALERT_FETCH_SUCCESS'; +const ALERT_FETCH_FAILURE = 'ALERT_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchAlert = createAction(ALERT_FETCH); +export const resetAlert = createAction(ALERT_RESET); + +export const request = createAction(ALERT_FETCH_REQUEST); +export const success = createAction(ALERT_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(ALERT_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultAlertState = { + isFetching: false, + response: { + atMeInfo: { count: 0 }, + replyInfo: { count: 0 }, + pmInfos: [], + systemInfo: { count: 0 } + } +}; + +export default handleActions({ + [ALERT_FETCH_REQUEST]: (state, action) => ({ + ...state, + isFetching: true + }), + [ALERT_FETCH_SUCCESS]: (state, action) => ({ + ...state, + isFetching: false, + response: action.payload.body + }), + [ALERT_FETCH_FAILURE]: (state, action) => ({ + ...state, + isFetching: false + }), + [MARK_AT_ME_AS_READ]: (state, action) => ({ + ...state, + response: { + ...state.response, + atMeInfo: { count: 0 } + } + }), + [MARK_REPLY_AS_READ]: (state, action) => ({ + ...state, + response: { + ...state.response, + replyInfo: { count: 0 }, + } + }), + [MARK_PM_AS_READ]: (state, action) => { + let { plid } = action.payload; + return { + ...state, + response: { + ...state.response, + pmInfos: state.response.pmInfos.filter(item => item.plid !== plid) + } + }; + }, + [MARK_SYSTEM_AS_READ]: (state, action) => ({ + ...state, + response: { + ...state.response, + systemInfo: { count: 0 }, + } + }), + [ALERT_RESET]: () => defaultAlertState, + [REMOVE_CACHE]: () => defaultAlertState +}, defaultAlertState); diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index e192ad2..1a8a2b6 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -23,7 +23,7 @@ import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; import { getUserFromStorage } from '~/actions/authorizeAction'; import { retrieveSettingsFromStorage } from '~/common/modules/settings/settings.ducks'; -import { fetchAlerts } from '~/actions/message/alertAction'; +import { fetchAlert } from '~/common/modules/message/alert.ducks'; import { ALERT_POLL_FREQUENCY } from '~/config'; import colors from '~/common/styles/colors.style'; @@ -153,12 +153,12 @@ class AppRoot extends Component { } if (!this.timer && nextEnableNotification) { - this.timer = setInterval(() => { this.fetchAlerts(); }, 1000 * ALERT_POLL_FREQUENCY); + this.timer = setInterval(() => { this.fetchAlert(); }, 1000 * ALERT_POLL_FREQUENCY); } } - fetchAlerts() { - this.props.fetchAlerts(); + fetchAlert() { + this.props.fetchAlert(); } componentWillUnmount() { @@ -188,5 +188,5 @@ function mapStateToProps({ user, settings }) { export default connect(mapStateToProps, { getUserFromStorage, retrieveSettingsFromStorage, - fetchAlerts + fetchAlert })(AppRoot); diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 38b4269..23421a0 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -14,7 +14,7 @@ import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; import { retrieveSettingsFromStorage, storeSettingsToStorage } from '~/common/modules/settings/settings.ducks'; -import { resetAlerts } from '~/actions/message/alertAction'; +import { resetAlert } from '~/common/modules/message/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from '~/containers/Settings/Settings.style'; @@ -40,7 +40,7 @@ class Settings extends Component { handleNotificationValueChange(value) { this.props.storeSettingsToStorage({ enableNotification: value }); // Clear message alters. - this.props.resetAlerts(); + this.props.resetAlert(); } handlePublishDialogValueChange(value) { @@ -91,5 +91,5 @@ function mapStateToProps({ settings }) { export default connect(mapStateToProps, { retrieveSettingsFromStorage, storeSettingsToStorage, - resetAlerts + resetAlert })(Settings); diff --git a/src/reducers/index.js b/src/reducers/index.js index ba1f6d6..c8e09dd 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -9,7 +9,7 @@ import pmSessionList from './message/pmSessionList'; import userTopicList from './user/topicList'; import pmList from './message/pmList'; import send from './message/send'; -import alert from './message/alert'; +import alert from '~/common/modules/message/alert.ducks'; import settings from '~/common/modules/settings/settings.ducks'; import userItem from './user/userItem'; import friendList from './user/friendList'; diff --git a/src/reducers/message/alert.js b/src/reducers/message/alert.js deleted file mode 100644 index 48a32a4..0000000 --- a/src/reducers/message/alert.js +++ /dev/null @@ -1,89 +0,0 @@ -import _ from 'lodash'; -import { - RESET, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/message/alertAction'; -import { - MARK_AT_ME_AS_READ, - MARK_REPLY_AS_READ, - MARK_SYSTEM_AS_READ -} from '~/actions/message/notifyListAction'; -import { MARK_PM_AS_READ } from '~/actions/message/pmSessionListAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultAlertState = { - isFetching: false, - response: { - atMeInfo: { count: 0 }, - replyInfo: { count: 0 }, - pmInfos: [], - systemInfo: { count: 0 } - } -}; - -export default function alert(state = defaultAlertState, action) { - switch (action.type) { - case REQUEST_STARTED: { - return { - ...state, - isFetching: true - }; - } - case REQUEST_COMPELTED: - return { - ...state, - isFetching: false, - response: action.payload.body - }; - case REQUEST_FAILED: { - return { - ...state, - isFetching: false, - }; - } - case MARK_AT_ME_AS_READ: { - return { - ...state, - response: { - ...state.response, - atMeInfo: { count: 0 } - } - }; - } - case MARK_REPLY_AS_READ: { - return { - ...state, - response: { - ...state.response, - replyInfo: { count: 0 }, - } - }; - } - case MARK_PM_AS_READ: { - let { plid } = action.payload; - return { - ...state, - response: { - ...state.response, - pmInfos: state.response.pmInfos.filter(item => item.plid !== plid) - } - }; - } - case MARK_SYSTEM_AS_READ: { - return { - ...state, - response: { - ...state.response, - systemInfo: { count: 0 }, - } - }; - } - case RESET: - case REMOVE_CACHE: - return defaultAlertState; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 9b463e7..7705415 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -11,7 +11,7 @@ import * as topicActions from '~/common/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; import * as pmListActions from '~/actions/message/pmListAction'; import * as sendActions from '~/actions/message/sendAction'; -import * as alertActions from '~/actions/message/alertAction'; +import * as alertActions from '~/common/modules/message/alert.ducks'; import * as settingsActions from '~/common/modules/settings/settings.ducks'; import * as userActions from '~/actions/user/userAction'; import * as friendListActions from '~/actions/user/friendListAction'; @@ -30,7 +30,7 @@ const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const sendMessageApi = fetchResource.bind(null, sendActions, api.sendMessage); -const fetchAlertsApi = fetchResource.bind(null, alertActions, api.fetchAlerts); +const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); const fetchUserApi = fetchResource.bind(null, userActions, api.fetchUser); const fetchFriendListApi = fetchResource.bind(null, friendListActions, api.fetchFriendList); @@ -228,8 +228,8 @@ function* watchSendMessage() { function* watchAlerts() { while(true) { - const { payload } = yield take(alertActions.REQUEST); - yield fork(fetchAlertsApi, payload); + const { payload } = yield take(alertActions.ALERT_FETCH); + yield fork(fetchAlertApi, payload); } } diff --git a/src/services/api.js b/src/services/api.js index eed84cd..a709d12 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -292,7 +292,7 @@ export default { return callApi(`message/pmadmin`, fetchOptions); }, - fetchAlerts: () => { + fetchAlert: () => { // Specify `sdkVersion` to get `systemInfo` instead of `friendInfo`. // // API source code: From 101ddfde4da006c62fc77b0a57166af9b4b2dae5 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 12 Aug 2018 11:09:22 +0800 Subject: [PATCH 10/58] refactor: introduce ducks pattern for notify list and pm session list --- src/actions/index.js | 1 - src/actions/message/notifyListAction.js | 34 ----- src/actions/message/pmSessionListAction.js | 16 -- src/common/modules/message/alert.ducks.js | 4 +- .../modules/message/notifyList.ducks.js | 140 ++++++++++++++++++ .../modules/message/pmSessionList.ducks.js | 110 ++++++++++++++ src/containers/Message/Message.js | 4 +- src/reducers/index.js | 4 +- src/reducers/message/notifyList.js | 105 ------------- src/reducers/message/pmSessionList.js | 96 ------------ src/sagas/index.js | 8 +- 11 files changed, 260 insertions(+), 262 deletions(-) delete mode 100644 src/actions/message/notifyListAction.js delete mode 100644 src/actions/message/pmSessionListAction.js create mode 100644 src/common/modules/message/notifyList.ducks.js create mode 100644 src/common/modules/message/pmSessionList.ducks.js delete mode 100644 src/reducers/message/notifyList.js delete mode 100644 src/reducers/message/pmSessionList.js diff --git a/src/actions/index.js b/src/actions/index.js index 277e20c..6bd6ffc 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,4 +1,3 @@ -export notifyListAction from './message/notifyListAction'; export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; export userAction from './user/userAction'; diff --git a/src/actions/message/notifyListAction.js b/src/actions/message/notifyListAction.js deleted file mode 100644 index 83f3ed7..0000000 --- a/src/actions/message/notifyListAction.js +++ /dev/null @@ -1,34 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const MARK_AT_ME_AS_READ = Symbol(); -export const MARK_REPLY_AS_READ = Symbol(); -export const MARK_SYSTEM_AS_READ = Symbol(); -export const fetchNotifyList = createAction(REQUEST); -export const invalidateNotifyList = createAction(INVALIDATE); - -const markAtMeAsRead = createAction(MARK_AT_ME_AS_READ); -const markReplyAsRead = createAction(MARK_REPLY_AS_READ); -const markSystemAsRead = createAction(MARK_SYSTEM_AS_READ); - -// Update unread message count immediately instead of -// clearing them with next poll after 0 ~ 15s. -export const successfulCallback = (payload) => { - switch (payload.notifyType) { - case 'at': - return markAtMeAsRead(); - case 'post': - return markReplyAsRead(); - case 'system': - return markSystemAsRead(); - } -} - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/actions/message/pmSessionListAction.js b/src/actions/message/pmSessionListAction.js deleted file mode 100644 index 0e1f666..0000000 --- a/src/actions/message/pmSessionListAction.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const MARK_PM_AS_READ = Symbol(); -export const fetchPmSessionList = createAction(REQUEST); -export const invalidatePmSessionList = createAction(INVALIDATE); -export const markPmAsRead = createAction(MARK_PM_AS_READ); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/common/modules/message/alert.ducks.js b/src/common/modules/message/alert.ducks.js index 1b5d758..f47d9ae 100644 --- a/src/common/modules/message/alert.ducks.js +++ b/src/common/modules/message/alert.ducks.js @@ -4,8 +4,8 @@ import { MARK_AT_ME_AS_READ, MARK_REPLY_AS_READ, MARK_SYSTEM_AS_READ -} from '~/actions/message/notifyListAction'; -import { MARK_PM_AS_READ } from '~/actions/message/pmSessionListAction'; +} from '~/common/modules/message/notifyList.ducks'; +import { MARK_PM_AS_READ } from '~/common/modules/message/pmSessionList.ducks'; import { REMOVE_CACHE } from '~/actions/authorizeAction'; // ********************************* diff --git a/src/common/modules/message/notifyList.ducks.js b/src/common/modules/message/notifyList.ducks.js new file mode 100644 index 0000000..773c769 --- /dev/null +++ b/src/common/modules/message/notifyList.ducks.js @@ -0,0 +1,140 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; + +// ********************************* +// Actions +// ********************************* + +export const NOTIFY_LIST_FETCH = 'NOTIFY_LIST_FETCH'; +export const NOTIFY_LIST_INVALIDATE = 'NOTIFY_LIST_INVALIDATE'; + +const NOTIFY_LIST_FETCH_REQUEST = 'NOTIFY_LIST_FETCH_REQUEST'; +const NOTIFY_LIST_FETCH_SUCCESS = 'NOTIFY_LIST_FETCH_SUCCESS'; +const NOTIFY_LIST_FETCH_FAILURE = 'NOTIFY_LIST_FETCH_FAILURE'; + +export const MARK_AT_ME_AS_READ = 'MARK_AT_ME_AS_READ'; +export const MARK_REPLY_AS_READ = 'MARK_REPLY_AS_READ'; +export const MARK_SYSTEM_AS_READ = 'MARK_SYSTEM_AS_READ'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchNotifyList = createAction(NOTIFY_LIST_FETCH); +export const invalidateNotifyList = createAction(NOTIFY_LIST_INVALIDATE); + +const markAtMeAsRead = createAction(MARK_AT_ME_AS_READ); +const markReplyAsRead = createAction(MARK_REPLY_AS_READ); +const markSystemAsRead = createAction(MARK_SYSTEM_AS_READ); + +// Update unread message count immediately instead of +// clearing them with next poll after 0 ~ 15s. +export const successfulCallback = (payload) => { + switch (payload.notifyType) { + case 'at': + return markAtMeAsRead(); + case 'post': + return markReplyAsRead(); + case 'system': + return markSystemAsRead(); + } +} + +export const request = createAction(NOTIFY_LIST_FETCH_REQUEST); +export const success = createAction(NOTIFY_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(NOTIFY_LIST_FETCH_FAILURE, null, (...args) => args[1]); + +// ********************************* +// Reducer +// ********************************* + +const defaultState = {}; +const defaultNotifyListState = { + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + notifyType: null, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [NOTIFY_LIST_INVALIDATE]: (state, action) => { + let { notifyType } = action.payload; + return { + ...state, + [notifyType]: { + ..._.get(state, notifyType, defaultNotifyListState), + didInvalidate: true + } + }; + }, + [NOTIFY_LIST_FETCH_REQUEST]: (state, action) => { + let { notifyType, isEndReached } = action.payload; + return { + ...state, + [notifyType]: { + ..._.get(state, notifyType, defaultNotifyListState), + isRefreshing: !isEndReached, + isEndReached: isEndReached, + didInvalidate: false + } + }; + }, + [NOTIFY_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: notifyList, + meta: { + notifyType + } + } = action; + + // `list` is `[]` for `system` type. + if (notifyType === 'system') { + notifyList.list = notifyList.body.data; + } + + return { + ...state, + [notifyType]: { + ..._.get(state, notifyType, defaultNotifyListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + notifyType, + list: getNewCache(state, notifyList.list, notifyType, notifyList.page), + hasMore: !!notifyList.has_next, + page: notifyList.page, + errCode: notifyList.errcode + } + }; + }, + [NOTIFY_LIST_FETCH_FAILURE]: (state, action) => { + let { notifyType } = action.meta; + return { + ...state, + [notifyType]: { + ..._.get(state, notifyType, defaultNotifyListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false + } + }; + }, + [REMOVE_CACHE]: () => defaultState +}, defaultState); + +function getNewCache(oldState, notifyList, notifyType, page) { + let newNotifyList = []; + + if (page !== 1) { + newNotifyList = oldState[notifyType].list.concat(notifyList); + } else { + newNotifyList = notifyList; + } + + return newNotifyList; +} diff --git a/src/common/modules/message/pmSessionList.ducks.js b/src/common/modules/message/pmSessionList.ducks.js new file mode 100644 index 0000000..9f40031 --- /dev/null +++ b/src/common/modules/message/pmSessionList.ducks.js @@ -0,0 +1,110 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; + +// ********************************* +// Actions +// ********************************* + +export const PM_SESSION_LIST_FETCH = 'PM_SESSION_LIST_FETCH'; +export const PM_SESSION_LIST_INVALIDATE = 'PM_SESSION_LIST_INVALIDATE'; + +const PM_SESSION_LIST_FETCH_REQUEST = 'PM_SESSION_LIST_FETCH_REQUEST'; +const PM_SESSION_LIST_FETCH_SUCCESS = 'PM_SESSION_LIST_FETCH_SUCCESS'; +const PM_SESSION_LIST_FETCH_FAILURE = 'PM_SESSION_LIST_FETCH_FAILURE'; + +export const MARK_PM_AS_READ = 'MARK_PM_AS_READ'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchPmSessionList = createAction(PM_SESSION_LIST_FETCH); +export const invalidatePmSessionList = createAction(PM_SESSION_LIST_INVALIDATE); + +export const markPmAsRead = createAction(MARK_PM_AS_READ); + +export const request = createAction(PM_SESSION_LIST_FETCH_REQUEST); +export const success = createAction(PM_SESSION_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(PM_SESSION_LIST_FETCH_FAILURE, null, (...args) => args[1]); + +// ********************************* +// Reducer +// ********************************* + +const defaultPmSessionListState = { + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [PM_SESSION_LIST_INVALIDATE]: (state, action) => ({ + ...state, + didInvalidate: true + }), + [MARK_PM_AS_READ]: (state, action) => { + let { plid } = action.payload; + return { + ...state, + list: state.list.map(item => { + if (item.plid === plid) { + item.isNew = false; + } + return item; + }) + }; + }, + [PM_SESSION_LIST_FETCH_REQUEST]: (state, action) => { + let { isEndReached } = action.payload; + return { + ...state, + isRefreshing: !isEndReached, + isEndReached: isEndReached, + didInvalidate: false + }; + }, + [PM_SESSION_LIST_FETCH_SUCCESS]: (state, action) => { + let { + meta, + payload, + payload: { + body: pmSessionList + } + } = action; + + return { + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: getNewCache(state, pmSessionList.list, meta.page), + hasMore: !!pmSessionList.hasNext, + page: meta.page, + errCode: payload.errcode + }; + }, + [PM_SESSION_LIST_FETCH_FAILURE]: (state, action) => ({ + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false + }), + [REMOVE_CACHE]: () => defaultPmSessionListState +}, defaultPmSessionListState); + +function getNewCache(oldState, pmSessionList, page) { + let newPmSessionList = []; + + if (page !== 1) { + newPmSessionList = oldState.list.concat(pmSessionList); + } else { + newPmSessionList = pmSessionList; + } + + return newPmSessionList; +} diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index 1532621..ef54cd6 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -8,8 +8,8 @@ import NotifyList from '~/components/NotifyList/NotifyList'; import PmSessionList from '~/components/PmSessionList/PmSessionList'; import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; -import { invalidateNotifyList, fetchNotifyList } from '~/actions/message/notifyListAction'; -import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/actions/message/pmSessionListAction'; +import { invalidateNotifyList, fetchNotifyList } from '~/common/modules/message/notifyList.ducks'; +import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/common/modules/message/pmSessionList.ducks'; import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index c8e09dd..7eb9d8a 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -4,8 +4,8 @@ import forumList from '~/common/modules/forum/forumList.ducks'; import topicList from '~/common/modules/topic/topicList.ducks'; import topicItem from '~/common/modules/topic/topic.ducks'; import searchList from '~/common/modules/topic/searchList.ducks'; -import notifyList from './message/notifyList'; -import pmSessionList from './message/pmSessionList'; +import notifyList from '~/common/modules/message/notifyList.ducks'; +import pmSessionList from '~/common/modules/message/pmSessionList.ducks'; import userTopicList from './user/topicList'; import pmList from './message/pmList'; import send from './message/send'; diff --git a/src/reducers/message/notifyList.js b/src/reducers/message/notifyList.js deleted file mode 100644 index edce8fd..0000000 --- a/src/reducers/message/notifyList.js +++ /dev/null @@ -1,105 +0,0 @@ -import _ from 'lodash'; -import { - INVALIDATE, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/message/notifyListAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultState = {}; -const defaultNotifyListState = { - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - notifyType: null, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function notifyList(state = defaultState, action) { - switch (action.type) { - case INVALIDATE: { - let { notifyType } = action.payload; - - return { - ...state, - [notifyType]: { - ..._.get(state, notifyType, defaultNotifyListState), - didInvalidate: true - } - }; - } - case REQUEST_STARTED: { - let { notifyType, isEndReached } = action.payload; - - return { - ...state, - [notifyType]: { - ..._.get(state, notifyType, defaultNotifyListState), - isRefreshing: !isEndReached, - isEndReached: isEndReached, - didInvalidate: false - } - }; - } - case REQUEST_COMPELTED: - let { - payload: notifyList, - meta: { - notifyType - } - } = action; - - // `list` is `[]` for `system` type. - if (notifyType === 'system') { - notifyList.list = notifyList.body.data; - } - - return { - ...state, - [notifyType]: { - ..._.get(state, notifyType, defaultNotifyListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - notifyType, - list: getNewCache(state, notifyList.list, notifyType, notifyList.page), - hasMore: !!notifyList.has_next, - page: notifyList.page, - errCode: notifyList.errcode - } - }; - case REQUEST_FAILED: { - let { notifyType } = action.meta; - - return { - ...state, - [notifyType]: { - ..._.get(state, notifyType, defaultNotifyListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false - } - }; - } - case REMOVE_CACHE: - return defaultState; - default: - return state; - } -} - -function getNewCache(oldState, notifyList, notifyType, page) { - let newNotifyList = []; - - if (page !== 1) { - newNotifyList = oldState[notifyType].list.concat(notifyList); - } else { - newNotifyList = notifyList; - } - - return newNotifyList; -} diff --git a/src/reducers/message/pmSessionList.js b/src/reducers/message/pmSessionList.js deleted file mode 100644 index 6d1e1e0..0000000 --- a/src/reducers/message/pmSessionList.js +++ /dev/null @@ -1,96 +0,0 @@ -import _ from 'lodash'; -import { - INVALIDATE, - MARK_PM_AS_READ, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/message/pmSessionListAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultPmSessionListState = { - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function pmSessionList(state = defaultPmSessionListState, action) { - switch (action.type) { - case INVALIDATE: { - return { - ...state, - didInvalidate: true - }; - } - case MARK_PM_AS_READ: { - let { plid } = action.payload; - - return { - ...state, - list: state.list.map(item => { - if (item.plid === plid) { - item.isNew = false; - } - return item; - }) - }; - } - case REQUEST_STARTED: { - let { isEndReached } = action.payload; - - return { - ...state, - isRefreshing: !isEndReached, - isEndReached: isEndReached, - didInvalidate: false - }; - } - case REQUEST_COMPELTED: - let { - meta, - payload, - payload: { - body: pmSessionList - } - } = action; - - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: getNewCache(state, pmSessionList.list, meta.page), - hasMore: !!pmSessionList.hasNext, - page: meta.page, - errCode: payload.errcode - }; - case REQUEST_FAILED: { - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false - }; - } - case REMOVE_CACHE: - return defaultPmSessionListState; - default: - return state; - } -} - -function getNewCache(oldState, pmSessionList, page) { - let newPmSessionList = []; - - if (page !== 1) { - newPmSessionList = oldState.list.concat(pmSessionList); - } else { - newPmSessionList = pmSessionList; - } - - return newPmSessionList; -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 7705415..d70db21 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -5,10 +5,10 @@ import * as authorizeActions from '~/actions/authorizeAction'; import * as topicListActions from '~/common/modules/topic/topicList.ducks'; import * as userTopicListActions from '~/actions/user/topicListAction'; import * as forumListActions from '~/common/modules/forum/forumList.ducks'; -import * as notifyListActions from '~/actions/message/notifyListAction'; +import * as notifyListActions from '~/common/modules/message/notifyList.ducks'; import * as searchListActions from '~/common/modules/topic/searchList.ducks'; import * as topicActions from '~/common/modules/topic/topic.ducks'; -import * as pmSessionListActions from '~/actions/message/pmSessionListAction'; +import * as pmSessionListActions from '~/common/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/actions/message/pmListAction'; import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/common/modules/message/alert.ducks'; @@ -154,7 +154,7 @@ function* fetchForumList(payload) { function* watchNotifyList() { while(true) { - const { payload } = yield take(notifyListActions.REQUEST); + const { payload } = yield take(notifyListActions.NOTIFY_LIST_FETCH); yield fork(fetchNotifyList, payload); } } @@ -191,7 +191,7 @@ function* watchTopic() { function* watchPmSessionList() { while(true) { - const { payload } = yield take(pmSessionListActions.REQUEST); + const { payload } = yield take(pmSessionListActions.PM_SESSION_LIST_FETCH); yield fork(fetchPmSessionList, payload); } } From 8412f2284edc65642cb2eb2415acf06801903359 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 12 Aug 2018 11:30:22 +0800 Subject: [PATCH 11/58] refactor: introduce ducks pattern for pm list --- src/actions/message/pmListAction.js | 16 ---- src/common/modules/message/pmList.ducks.js | 90 ++++++++++++++++++++++ src/containers/PmList/PmList.js | 2 +- src/reducers/index.js | 2 +- src/reducers/message/pmList.js | 77 ------------------ src/sagas/index.js | 4 +- 6 files changed, 94 insertions(+), 97 deletions(-) delete mode 100644 src/actions/message/pmListAction.js create mode 100644 src/common/modules/message/pmList.ducks.js delete mode 100644 src/reducers/message/pmList.js diff --git a/src/actions/message/pmListAction.js b/src/actions/message/pmListAction.js deleted file mode 100644 index 57ed515..0000000 --- a/src/actions/message/pmListAction.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const RESET_RESPONSE_STATUS = Symbol(); -export const fetchPmList = createAction(REQUEST); -export const resetPmList = createAction(RESET); -export const resetPmListResponseStatus = createAction(RESET_RESPONSE_STATUS); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/common/modules/message/pmList.ducks.js b/src/common/modules/message/pmList.ducks.js new file mode 100644 index 0000000..88087b5 --- /dev/null +++ b/src/common/modules/message/pmList.ducks.js @@ -0,0 +1,90 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; + +// ********************************* +// Actions +// ********************************* + +export const PM_LIST_FETCH = 'PM_LIST_FETCH'; +export const PM_LIST_RESET = 'PM_LIST_RESET'; +export const PM_LIST_RESPONSE_STATUS_RESET = 'PM_LIST_RESPONSE_STATUS_RESET'; + +const PM_LIST_FETCH_REQUEST = 'PM_LIST_FETCH_REQUEST'; +const PM_LIST_FETCH_SUCCESS = 'PM_LIST_FETCH_SUCCESS'; +const PM_LIST_FETCH_FAILURE = 'PM_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchPmList = createAction(PM_LIST_FETCH); +export const resetPmList = createAction(PM_LIST_RESET); +export const resetPmListResponseStatus = createAction(PM_LIST_RESPONSE_STATUS_RESET); + +export const request = createAction(PM_LIST_FETCH_REQUEST); +export const success = createAction(PM_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(PM_LIST_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultPmListState = { + isRefreshing: false, + list: [], + hasPrev: false, + page: 0, + errCode: '', + user: '', + response: '' +}; + +export default handleActions({ + [PM_LIST_FETCH_REQUEST]: (state, action) => ({ + ...state, + isRefreshing: true + }), + [PM_LIST_FETCH_SUCCESS]: (state, action) => { + let { + meta, + payload, + payload: { + body: { + pmList + } + } + } = action; + + let msgList = null; + + if (meta.page !== 1) { + msgList = state.list.concat(pmList[0].msgList.reverse()); + } else { + msgList = pmList[0].msgList.reverse(); + } + + return { + ...state, + isRefreshing: false, + list: msgList, + hasPrev: !!pmList[0].hasPrev, + page: meta.page, + errCode: payload.errcode, + user: { + id: pmList[0].fromUid, + name: pmList[0].name, + avatar: pmList[0].avatar + }, + response: payload + }; + }, + [PM_LIST_FETCH_FAILURE]: (state, action) => ({ + ...state, + isRefreshing: false + }), + [PM_LIST_RESET]: () => defaultPmListState, + [PM_LIST_RESPONSE_STATUS_RESET]: (state, action) => ({ + ...state, + response: '' + }) +}, defaultPmListState); diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index 96b278c..b54b797 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -20,7 +20,7 @@ import { fetchPmList, resetPmList, resetPmListResponseStatus -} from '~/actions/message/pmListAction'; +} from '~/common/modules/message/pmList.ducks'; import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '~/config'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index 7eb9d8a..b033257 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -7,7 +7,7 @@ import searchList from '~/common/modules/topic/searchList.ducks'; import notifyList from '~/common/modules/message/notifyList.ducks'; import pmSessionList from '~/common/modules/message/pmSessionList.ducks'; import userTopicList from './user/topicList'; -import pmList from './message/pmList'; +import pmList from '~/common/modules/message/pmList.ducks'; import send from './message/send'; import alert from '~/common/modules/message/alert.ducks'; import settings from '~/common/modules/settings/settings.ducks'; diff --git a/src/reducers/message/pmList.js b/src/reducers/message/pmList.js deleted file mode 100644 index ae82651..0000000 --- a/src/reducers/message/pmList.js +++ /dev/null @@ -1,77 +0,0 @@ -import _ from 'lodash'; -import { - RESET, - RESET_RESPONSE_STATUS, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/message/pmListAction'; - -const defaultPmListState = { - isRefreshing: false, - list: [], - hasPrev: false, - page: 0, - errCode: '', - user: '', - response: '' -}; - -export default function pmList(state = defaultPmListState, action) { - switch (action.type) { - case REQUEST_STARTED: { - return { - ...state, - isRefreshing: true - }; - } - case REQUEST_COMPELTED: - let { - meta, - payload, - payload: { - body: { - pmList - } - } - } = action; - - let msgList = null; - - if (meta.page !== 1) { - msgList = state.list.concat(pmList[0].msgList.reverse()); - } else { - msgList = pmList[0].msgList.reverse(); - } - - return { - ...state, - isRefreshing: false, - list: msgList, - hasPrev: !!pmList[0].hasPrev, - page: meta.page, - errCode: payload.errcode, - user: { - id: pmList[0].fromUid, - name: pmList[0].name, - avatar: pmList[0].avatar - }, - response: payload - }; - case REQUEST_FAILED: { - return { - ...state, - isRefreshing: false, - }; - } - case RESET: - return defaultPmListState; - case RESET_RESPONSE_STATUS: - return { - ...state, - response: '' - }; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index d70db21..554d53e 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -9,7 +9,7 @@ import * as notifyListActions from '~/common/modules/message/notifyList.ducks'; import * as searchListActions from '~/common/modules/topic/searchList.ducks'; import * as topicActions from '~/common/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/common/modules/message/pmSessionList.ducks'; -import * as pmListActions from '~/actions/message/pmListAction'; +import * as pmListActions from '~/common/modules/message/pmList.ducks'; import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/common/modules/message/alert.ducks'; import * as settingsActions from '~/common/modules/settings/settings.ducks'; @@ -210,7 +210,7 @@ function* fetchPmSessionList(payload) { function* watchPmList() { while(true) { - const { payload } = yield take(pmListActions.REQUEST); + const { payload } = yield take(pmListActions.PM_LIST_FETCH); yield fork(fetchPmListApi, payload); } } From 693406b786c0b62dc69d65709a9b8aa0a149bc64 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 12 Aug 2018 11:47:11 +0800 Subject: [PATCH 12/58] refactor: introduce ducks pattern for friend list --- src/actions/user/friendListAction.js | 14 ---- src/common/modules/user/friendList.ducks.js | 79 +++++++++++++++++++ .../FriendListModal/FriendListModal.js | 2 +- src/reducers/index.js | 2 +- src/reducers/user/friendList.js | 63 --------------- src/sagas/index.js | 4 +- 6 files changed, 83 insertions(+), 81 deletions(-) delete mode 100644 src/actions/user/friendListAction.js create mode 100644 src/common/modules/user/friendList.ducks.js delete mode 100644 src/reducers/user/friendList.js diff --git a/src/actions/user/friendListAction.js b/src/actions/user/friendListAction.js deleted file mode 100644 index 2cc13c5..0000000 --- a/src/actions/user/friendListAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const fetchFriendList = createAction(REQUEST); -export const invalidateFriendList = createAction(INVALIDATE); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/common/modules/user/friendList.ducks.js b/src/common/modules/user/friendList.ducks.js new file mode 100644 index 0000000..1a42a57 --- /dev/null +++ b/src/common/modules/user/friendList.ducks.js @@ -0,0 +1,79 @@ +import { createAction, handleActions } from 'redux-actions'; + +// ********************************* +// Actions +// ********************************* + +export const FRIEND_LIST_FETCH = 'FRIEND_LIST_FETCH'; +export const FRIEND_LIST_INVALIDATE = 'FRIEND_LIST_INVALIDATE'; + +const FRIEND_LIST_FETCH_REQUEST = 'FRIEND_LIST_FETCH_REQUEST'; +const FRIEND_LIST_FETCH_SUCCESS = 'FRIEND_LIST_FETCH_SUCCESS'; +const FRIEND_LIST_FETCH_FAILURE = 'FRIEND_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchFriendList = createAction(FRIEND_LIST_FETCH); +export const invalidateFriendList = createAction(FRIEND_LIST_INVALIDATE); + +export const request = createAction(FRIEND_LIST_FETCH_REQUEST); +export const success = createAction(FRIEND_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(FRIEND_LIST_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultFriendListState = { + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [FRIEND_LIST_INVALIDATE]: (state, action) => ({ + ...state, + didInvalidate: true + }), + [FRIEND_LIST_FETCH_REQUEST]: (state, action) => { + let { isEndReached } = action.payload; + return { + ...state, + isRefreshing: !isEndReached, + isEndReached: isEndReached, + didInvalidate: false + }; + }, + [FRIEND_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: friendList + } = action; + + if (friendList.page !== 1 && friendList.list) { + friendList.list = state.list.concat(friendList.list); + } + + return { + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: friendList.list || [], + hasMore: !!friendList.has_next, + page: friendList.page, + errCode: friendList.errcode + }; + }, + [FRIEND_LIST_FETCH_FAILURE]: (state, action) => ({ + ...state, + isRefreshing: false, + isEndReached: false, + didInvalidate: false + }) +}, defaultFriendListState); diff --git a/src/components/FriendListModal/FriendListModal.js b/src/components/FriendListModal/FriendListModal.js index 6127716..0f3e3ee 100644 --- a/src/components/FriendListModal/FriendListModal.js +++ b/src/components/FriendListModal/FriendListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import FriendList from '~/components/FriendList/FriendList'; import Header from '~/components/Header/Header'; -import { invalidateFriendList, fetchFriendList } from '~/actions/user/friendListAction'; +import { invalidateFriendList, fetchFriendList } from '~/common/modules/user/friendList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index b033257..a03ea89 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -12,7 +12,7 @@ import send from './message/send'; import alert from '~/common/modules/message/alert.ducks'; import settings from '~/common/modules/settings/settings.ducks'; import userItem from './user/userItem'; -import friendList from './user/friendList'; +import friendList from '~/common/modules/user/friendList.ducks'; export default combineReducers({ forumList, diff --git a/src/reducers/user/friendList.js b/src/reducers/user/friendList.js deleted file mode 100644 index 3577d70..0000000 --- a/src/reducers/user/friendList.js +++ /dev/null @@ -1,63 +0,0 @@ -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED, - INVALIDATE -} from '~/actions/user/friendListAction'; - -const defaultSearchState = { - // indicate fetching via pull to refresh - isRefreshing: false, - // indicate fetching via end reached - isEndReached: false, - didInvalidate: false, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function search(state = defaultSearchState, action) { - switch (action.type) { - case INVALIDATE: - return { - ...state, - didInvalidate: true - }; - case REQUEST_STARTED: - return { - ...state, - isRefreshing: !action.payload.isEndReached, - isEndReached: action.payload.isEndReached, - didInvalidate: false - }; - case REQUEST_COMPELTED: - let { - payload: friendList - } = action; - - if (friendList.page !== 1 && friendList.list) { - friendList.list = state.list.concat(friendList.list); - } - - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: friendList.list || [], - hasMore: !!friendList.has_next, - page: friendList.page, - errCode: friendList.errcode - }; - case REQUEST_FAILED: - return { - ...state, - isRefreshing: false, - isEndReached: false, - didInvalidate: false - }; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 554d53e..46e1f04 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -14,7 +14,7 @@ import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/common/modules/message/alert.ducks'; import * as settingsActions from '~/common/modules/settings/settings.ducks'; import * as userActions from '~/actions/user/userAction'; -import * as friendListActions from '~/actions/user/friendListAction'; +import * as friendListActions from '~/common/modules/user/friendList.ducks'; import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; @@ -246,7 +246,7 @@ function* watchUsers() { function* watchFriendList() { while(true) { - const { payload } = yield take(friendListActions.REQUEST); + const { payload } = yield take(friendListActions.FRIEND_LIST_FETCH); yield fork(fetchFriendList, payload); } } From f4cab7e8b9fd9abf6ddfe15a4e65ddbb09554d1b Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 12 Aug 2018 12:56:28 +0800 Subject: [PATCH 13/58] refactor: introduce ducks pattern for user topic list --- src/actions/index.js | 1 - src/actions/user/topicListAction.js | 14 -- .../modules/user/userTopicList.ducks.js | 126 ++++++++++++++++++ src/containers/Individual/Individual.js | 2 +- src/reducers/index.js | 2 +- src/reducers/user/topicList.js | 113 ---------------- src/sagas/index.js | 4 +- 7 files changed, 130 insertions(+), 132 deletions(-) delete mode 100644 src/actions/user/topicListAction.js create mode 100644 src/common/modules/user/userTopicList.ducks.js delete mode 100644 src/reducers/user/topicList.js diff --git a/src/actions/index.js b/src/actions/index.js index 6bd6ffc..05a8af9 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,3 +1,2 @@ -export userTopicListAction from './user/topicListAction'; export authorizeAction from './authorizeAction'; export userAction from './user/userAction'; diff --git a/src/actions/user/topicListAction.js b/src/actions/user/topicListAction.js deleted file mode 100644 index a92f1a9..0000000 --- a/src/actions/user/topicListAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const INVALIDATE = Symbol(); -export const fetchUserTopicList = createAction(REQUEST); -export const invalidateUserTopicList = createAction(INVALIDATE); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED, null, (...args) => args[1]); diff --git a/src/common/modules/user/userTopicList.ducks.js b/src/common/modules/user/userTopicList.ducks.js new file mode 100644 index 0000000..a12b264 --- /dev/null +++ b/src/common/modules/user/userTopicList.ducks.js @@ -0,0 +1,126 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; +import { REMOVE_CACHE } from '~/actions/authorizeAction'; + +// ********************************* +// Actions +// ********************************* + +export const USER_TOPIC_LIST_FETCH = 'USER_TOPIC_LIST_FETCH'; +export const USER_TOPIC_LIST_INVALIDATE = 'USER_TOPIC_LIST_INVALIDATE'; + +const USER_TOPIC_LIST_FETCH_REQUEST = 'USER_TOPIC_LIST_FETCH_REQUEST'; +const USER_TOPIC_LIST_FETCH_SUCCESS = 'USER_TOPIC_LIST_FETCH_SUCCESS'; +const USER_TOPIC_LIST_FETCH_FAILURE = 'USER_TOPIC_LIST_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchUserTopicList = createAction(USER_TOPIC_LIST_FETCH); +export const invalidateUserTopicList = createAction(USER_TOPIC_LIST_INVALIDATE); + +export const request = createAction(USER_TOPIC_LIST_FETCH_REQUEST); +export const success = createAction(USER_TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(USER_TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); + +// ********************************* +// Reducer +// ********************************* + +const defaultState = {}; +const defaultUserTopicListState = { + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: [], + hasMore: false, + page: 0, + errCode: '' +}; + +export default handleActions({ + [USER_TOPIC_LIST_INVALIDATE]: (state, action) => { + let { userId, type } = action.payload; + return { + ...state, + [userId]: { + ..._.get(state, userId, {}), + [type]: { + ..._.get(state, [userId, type], defaultUserTopicListState), + didInvalidate: true + } + } + }; + }, + [USER_TOPIC_LIST_FETCH_REQUEST]: (state, action) => { + let { userId, type, isEndReached } = action.payload; + return { + ...state, + [userId]: { + ..._.get(state, userId, {}), + [type]: { + ..._.get(state, [userId, type], defaultUserTopicListState), + isRefreshing: !isEndReached, + isEndReached: isEndReached, + didInvalidate: false + } + } + }; + }, + [USER_TOPIC_LIST_FETCH_SUCCESS]: (state, action) => { + let { + payload: userTopicList, + meta: { + userId, + type + } + } = action; + return { + ...state, + [userId]: { + ..._.get(state, userId, {}), + [type]: { + ..._.get(state, [userId, type], defaultUserTopicListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false, + list: getNewCache(state, userTopicList.list, userId, type, userTopicList.page, userTopicList.rs), + hasMore: !!userTopicList.has_next, + page: userTopicList.page, + errCode: userTopicList.errcode + } + } + }; + }, + [USER_TOPIC_LIST_FETCH_FAILURE]: (state, action) => { + let { userId, type } = action.meta; + return { + ...state, + [userId]: { + ..._.get(state, userId, {}), + [type]: { + ..._.get(state, [userId, type], defaultUserTopicListState), + isRefreshing: false, + isEndReached: false, + didInvalidate: false + } + } + }; + }, + [REMOVE_CACHE]: () => defaultState +}, defaultState); + +function getNewCache(oldState, userTopicList, userId, type, page, isSuccessful) { + if (!isSuccessful) { return oldState.list; } + + let newUserTopicList = []; + + if (page !== 1) { + newUserTopicList = oldState[userId][type].list.concat(userTopicList); + } else { + newUserTopicList = userTopicList; + } + + return newUserTopicList; +} diff --git a/src/containers/Individual/Individual.js b/src/containers/Individual/Individual.js index 510f53c..a347e51 100644 --- a/src/containers/Individual/Individual.js +++ b/src/containers/Individual/Individual.js @@ -12,7 +12,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import { HeaderBackButton } from 'react-navigation'; import TopicList from '~/components/TopicList/TopicList'; -import { invalidateUserTopicList, fetchUserTopicList } from '~/actions/user/topicListAction'; +import { invalidateUserTopicList, fetchUserTopicList } from '~/common/modules/user/userTopicList.ducks'; import { AVATAR_ROOT } from '~/config'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index a03ea89..2b2e691 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -6,7 +6,7 @@ import topicItem from '~/common/modules/topic/topic.ducks'; import searchList from '~/common/modules/topic/searchList.ducks'; import notifyList from '~/common/modules/message/notifyList.ducks'; import pmSessionList from '~/common/modules/message/pmSessionList.ducks'; -import userTopicList from './user/topicList'; +import userTopicList from '~/common/modules/user/userTopicList.ducks'; import pmList from '~/common/modules/message/pmList.ducks'; import send from './message/send'; import alert from '~/common/modules/message/alert.ducks'; diff --git a/src/reducers/user/topicList.js b/src/reducers/user/topicList.js deleted file mode 100644 index f9108ff..0000000 --- a/src/reducers/user/topicList.js +++ /dev/null @@ -1,113 +0,0 @@ -import _ from 'lodash'; -import { - INVALIDATE, - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED -} from '~/actions/user/topicListAction'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; - -const defaultState = {}; -const defaultUserTopicListState = { - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: [], - hasMore: false, - page: 0, - errCode: '' -}; - -export default function userTopicList(state = defaultState, action) { - switch (action.type) { - case INVALIDATE: { - let { userId, type } = action.payload; - - return { - ...state, - [userId]: { - ..._.get(state, userId, {}), - [type]: { - ..._.get(state, [userId, type], defaultUserTopicListState), - didInvalidate: true - } - } - }; - } - case REQUEST_STARTED: { - let { userId, type, isEndReached } = action.payload; - - return { - ...state, - [userId]: { - ..._.get(state, userId, {}), - [type]: { - ..._.get(state, [userId, type], defaultUserTopicListState), - isRefreshing: !isEndReached, - isEndReached: isEndReached, - didInvalidate: false - } - } - }; - } - case REQUEST_COMPELTED: - let { - payload: userTopicList, - meta: { - userId, - type - } - } = action; - - return { - ...state, - [userId]: { - ..._.get(state, userId, {}), - [type]: { - ..._.get(state, [userId, type], defaultUserTopicListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false, - list: getNewCache(state, userTopicList.list, userId, type, userTopicList.page, userTopicList.rs), - hasMore: !!userTopicList.has_next, - page: userTopicList.page, - errCode: userTopicList.errcode - } - } - }; - case REQUEST_FAILED: { - let { userId, type } = action.meta; - - return { - ...state, - [userId]: { - ..._.get(state, userId, {}), - [type]: { - ..._.get(state, [userId, type], defaultUserTopicListState), - isRefreshing: false, - isEndReached: false, - didInvalidate: false - } - } - }; - } - case REMOVE_CACHE: - return defaultState; - default: - return state; - } -} - -function getNewCache(oldState, userTopicList, userId, type, page, isSuccessful) { - if (!isSuccessful) { return oldState.list; } - - let newUserTopicList = []; - - if (page !== 1) { - newUserTopicList = oldState[userId][type].list.concat(userTopicList); - } else { - newUserTopicList = userTopicList; - } - - return newUserTopicList; -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 46e1f04..4593ae3 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -3,7 +3,7 @@ import { take, fork, select, put, call } from 'redux-saga/effects'; import * as authorizeActions from '~/actions/authorizeAction'; import * as topicListActions from '~/common/modules/topic/topicList.ducks'; -import * as userTopicListActions from '~/actions/user/topicListAction'; +import * as userTopicListActions from '~/common/modules/user/userTopicList.ducks'; import * as forumListActions from '~/common/modules/forum/forumList.ducks'; import * as notifyListActions from '~/common/modules/message/notifyList.ducks'; import * as searchListActions from '~/common/modules/topic/searchList.ducks'; @@ -119,7 +119,7 @@ function* fetchTopicList(payload) { function* watchUserTopicList() { while(true) { - const { payload } = yield take(userTopicListActions.REQUEST); + const { payload } = yield take(userTopicListActions.USER_TOPIC_LIST_FETCH); yield fork(fetchUserTopicList, payload); } } From 5a9bf0d4a7b10d2af12d98098e1afd4dc59d9672 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 13 Aug 2018 14:30:35 +0800 Subject: [PATCH 14/58] refactor: introduce ducsk pattern for session --- src/actions/authorizeAction.js | 25 ------ src/actions/index.js | 1 - src/common/modules/forum/forumList.ducks.js | 4 +- src/common/modules/message/alert.ducks.js | 4 +- .../modules/message/notifyList.ducks.js | 4 +- .../modules/message/pmSessionList.ducks.js | 4 +- src/common/modules/topic/topicList.ducks.js | 4 +- src/common/modules/user/session.ducks.js | 82 +++++++++++++++++++ .../modules/user/userTopicList.ducks.js | 4 +- src/components/LoginModal/LoginModal.js | 42 +++++----- src/components/MenuProfile/MenuProfile.js | 12 +-- src/containers/ForumDetail/ForumDetail.js | 4 +- src/containers/Home/Home.js | 4 +- src/containers/Individual/Individual.js | 12 +-- src/containers/Information/Information.js | 10 +-- src/containers/Menu/Menu.js | 33 ++++---- src/containers/Message/Message.js | 4 +- src/containers/Navigator/Navigator.js | 14 ++-- src/containers/Search/Search.js | 4 +- src/containers/TopicDetail/TopicDetail.js | 18 ++-- src/reducers/index.js | 4 +- src/reducers/user.js | 61 -------------- src/sagas/index.js | 24 +++--- src/utils/request.js | 8 +- 24 files changed, 191 insertions(+), 195 deletions(-) delete mode 100644 src/actions/authorizeAction.js create mode 100644 src/common/modules/user/session.ducks.js delete mode 100644 src/reducers/user.js diff --git a/src/actions/authorizeAction.js b/src/actions/authorizeAction.js deleted file mode 100644 index 8a8e0a0..0000000 --- a/src/actions/authorizeAction.js +++ /dev/null @@ -1,25 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const userLogin = createAction(REQUEST); - -export const RETRIEVE = Symbol(); -export const getUserFromStorage = createAction(RETRIEVE); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); - -export const SET_AUTHRIZATION = Symbol(); -export const RESET_AUTHRIZATION = Symbol(); -export const RESET_AUTHRIZATION_RESULT = Symbol(); -export const setAuthrization = createAction(SET_AUTHRIZATION); -export const resetAuthrization = createAction(RESET_AUTHRIZATION); -export const resetAuthrizationResult = createAction(RESET_AUTHRIZATION_RESULT); - -export const REMOVE_CACHE = Symbol(); -export const cleanCache = createAction(REMOVE_CACHE); diff --git a/src/actions/index.js b/src/actions/index.js index 05a8af9..52a23df 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,2 +1 @@ -export authorizeAction from './authorizeAction'; export userAction from './user/userAction'; diff --git a/src/common/modules/forum/forumList.ducks.js b/src/common/modules/forum/forumList.ducks.js index 8f3e714..c0ac53d 100644 --- a/src/common/modules/forum/forumList.ducks.js +++ b/src/common/modules/forum/forumList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; import _ from 'lodash'; // ********************************* @@ -85,5 +85,5 @@ export default handleActions({ } }; }, - [REMOVE_CACHE]: () => defaultState + [LOGOUT]: () => defaultState }, defaultState); diff --git a/src/common/modules/message/alert.ducks.js b/src/common/modules/message/alert.ducks.js index f47d9ae..99b12f2 100644 --- a/src/common/modules/message/alert.ducks.js +++ b/src/common/modules/message/alert.ducks.js @@ -6,7 +6,7 @@ import { MARK_SYSTEM_AS_READ } from '~/common/modules/message/notifyList.ducks'; import { MARK_PM_AS_READ } from '~/common/modules/message/pmSessionList.ducks'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; // ********************************* // Actions @@ -90,5 +90,5 @@ export default handleActions({ } }), [ALERT_RESET]: () => defaultAlertState, - [REMOVE_CACHE]: () => defaultAlertState + [LOGOUT]: () => defaultAlertState }, defaultAlertState); diff --git a/src/common/modules/message/notifyList.ducks.js b/src/common/modules/message/notifyList.ducks.js index 773c769..2dd9e21 100644 --- a/src/common/modules/message/notifyList.ducks.js +++ b/src/common/modules/message/notifyList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; // ********************************* // Actions @@ -124,7 +124,7 @@ export default handleActions({ } }; }, - [REMOVE_CACHE]: () => defaultState + [LOGOUT]: () => defaultState }, defaultState); function getNewCache(oldState, notifyList, notifyType, page) { diff --git a/src/common/modules/message/pmSessionList.ducks.js b/src/common/modules/message/pmSessionList.ducks.js index 9f40031..67623d5 100644 --- a/src/common/modules/message/pmSessionList.ducks.js +++ b/src/common/modules/message/pmSessionList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; // ********************************* // Actions @@ -94,7 +94,7 @@ export default handleActions({ isEndReached: false, didInvalidate: false }), - [REMOVE_CACHE]: () => defaultPmSessionListState + [LOGOUT]: () => defaultPmSessionListState }, defaultPmSessionListState); function getNewCache(oldState, pmSessionList, page) { diff --git a/src/common/modules/topic/topicList.ducks.js b/src/common/modules/topic/topicList.ducks.js index c8a1c36..321c60c 100644 --- a/src/common/modules/topic/topicList.ducks.js +++ b/src/common/modules/topic/topicList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; import _ from 'lodash'; // ********************************* @@ -130,7 +130,7 @@ export default handleActions({ } }; }, - [REMOVE_CACHE]: () => defaultState + [LOGOUT]: () => defaultState }, defaultState); // map the fields of `type` to more clear names diff --git a/src/common/modules/user/session.ducks.js b/src/common/modules/user/session.ducks.js new file mode 100644 index 0000000..6bf93e7 --- /dev/null +++ b/src/common/modules/user/session.ducks.js @@ -0,0 +1,82 @@ +import { createAction, handleActions } from 'redux-actions'; + +// ********************************* +// Actions +// ********************************* + +export const LOGIN = 'LOGIN'; + +export const SESSION_RETRIEVE = 'SESSION_RETRIEVE'; +export const SESSION_SET = 'SESSION_SET'; +export const SESSION_RESET = 'SESSION_RESET'; +export const SESSION_RESULT_RESET = 'SESSION_RESULT_RESET'; + +const LOGIN_REQUEST = 'LOGIN_REQUEST'; +const LOGIN_SUCCESS = 'LOGIN_SUCCESS'; +const LOGIN_FAILURE = 'LOGIN_FAILURE'; + +export const LOGOUT = 'LOGOUT'; + +// ********************************* +// Action Creators +// ********************************* + +export const login = createAction(LOGIN); + +export const retrieveSessionFromStorage = createAction(SESSION_RETRIEVE); +export const setSession = createAction(SESSION_SET); +export const resetSession = createAction(SESSION_RESET); +export const resetSessionResult = createAction(SESSION_RESULT_RESET); + +export const request = createAction(LOGIN_REQUEST); +export const success = createAction(LOGIN_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(LOGIN_FAILURE); + +export const logout = createAction(LOGOUT); + +// ********************************* +// Reducer +// ********************************* + +const defaultSessionState = { + isFetching: false, + data: {}, + hasError: false, + result: false +}; + +export default handleActions({ + [SESSION_SET]: (state, action) => ({ + ...state, + data: action.payload + }), + [LOGIN_REQUEST]: (state, action) => ({ + ...state, + isFetching: true, + data: {}, + hasError: false, + result: false + }), + [LOGIN_SUCCESS]: (state, action) => ({ + ...state, + isFetching: false, + data: action.payload, + hasError: !!action.payload.errcode, + result: !!action.payload.rs + }), + [LOGIN_FAILURE]: (state, action) => ({ + ...state, + isFetching: false + }), + [SESSION_RESET]: () => defaultSessionState, + [SESSION_RESULT_RESET]: (state, action) => ({ + ...state, + result: false + }), + [LOGOUT]: (state, action) => { + if (!action.payload.isLogin) { + return defaultSessionState; + } + return state; + } +}, defaultSessionState); diff --git a/src/common/modules/user/userTopicList.ducks.js b/src/common/modules/user/userTopicList.ducks.js index a12b264..d6e50bc 100644 --- a/src/common/modules/user/userTopicList.ducks.js +++ b/src/common/modules/user/userTopicList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { REMOVE_CACHE } from '~/actions/authorizeAction'; +import { LOGOUT } from '~/common/modules/user/session.ducks'; // ********************************* // Actions @@ -108,7 +108,7 @@ export default handleActions({ } }; }, - [REMOVE_CACHE]: () => defaultState + [LOGOUT]: () => defaultState }, defaultState); function getNewCache(oldState, userTopicList, userId, type, page, isSuccessful) { diff --git a/src/components/LoginModal/LoginModal.js b/src/components/LoginModal/LoginModal.js index 63913ba..bc03b29 100644 --- a/src/components/LoginModal/LoginModal.js +++ b/src/components/LoginModal/LoginModal.js @@ -19,11 +19,11 @@ import Header from '~/components/Header/Header'; import SafariView from '~/services/SafariView'; import { REGISTER_URL } from '~/config'; import { - userLogin, - resetAuthrization, - resetAuthrizationResult, - cleanCache -} from '~/actions/authorizeAction'; + login, + resetSession, + resetSessionResult, + logout +} from '~/common/modules/user/session.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from './LoginModal.style'; @@ -45,20 +45,20 @@ class LoginModal extends Component { } componentWillReceiveProps(nextProps) { - let { isFetching, authrization, hasError, result } = nextProps.user; + let { isFetching, data, hasError, result } = nextProps.session; if (hasError) { - AlertIOS.alert('提示', authrization.errcode); - nextProps.resetAuthrization(); + AlertIOS.alert('提示', data.errcode); + nextProps.resetSession(); } if (result) { - this.props.resetAuthrizationResult(); - authrization = JSON.stringify(authrization); - AsyncStorage.setItem('authrization', authrization) + this.props.resetSessionResult(); + data = JSON.stringify(data); + AsyncStorage.setItem('session', data) .then(() => { - // Remove all cache except authrization. - this.props.cleanCache({ isLogin: true }); + // Remove all cache except session. + this.props.logout({ isLogin: true }); // Back home page. this.props.navigation.dispatch(resetAction); }); @@ -77,7 +77,7 @@ class LoginModal extends Component { } Keyboard.dismiss(); - this.props.userLogin({ + this.props.login({ userName, password }); @@ -85,7 +85,7 @@ class LoginModal extends Component { render() { let { - user: { + session: { isFetching }, navigation @@ -148,15 +148,15 @@ class LoginModal extends Component { } } -function mapStateToProps({ user }) { +function mapStateToProps({ session }) { return { - user + session }; } export default connect(mapStateToProps, { - userLogin, - resetAuthrization, - resetAuthrizationResult, - cleanCache + login, + resetSession, + resetSessionResult, + logout })(LoginModal); diff --git a/src/components/MenuProfile/MenuProfile.js b/src/components/MenuProfile/MenuProfile.js index 7a133ed..9f239f3 100644 --- a/src/components/MenuProfile/MenuProfile.js +++ b/src/components/MenuProfile/MenuProfile.js @@ -11,11 +11,13 @@ import styles from './MenuProfile.style'; export default class MenuProfile extends Component { render() { let { - authrization: { - uid, - token, - avatar, - userName, + session: { + data: { + uid, + token, + avatar, + userName + } }, navigation } = this.props; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index d1490b6..700164e 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -207,9 +207,9 @@ class ForumDetail extends Component { } } -function mapStateToProps({ topicList, forumList, user }) { +function mapStateToProps({ topicList, forumList, session }) { return { - userId: _.get(user, ['authrization', 'uid']), + userId: _.get(session, ['data', 'uid']), topicList, forumList }; diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index ca84019..0d639e6 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -135,9 +135,9 @@ class Home extends Component { } } -function mapStateToProps({ topicList, alert, user }) { +function mapStateToProps({ topicList, alert, session }) { return { - userId: _.get(user, ['authrization', 'uid']), + userId: _.get(session, ['data', 'uid']), topicList, alertCount: getAlertCount(alert) }; diff --git a/src/containers/Individual/Individual.js b/src/containers/Individual/Individual.js index a347e51..8f9ee50 100644 --- a/src/containers/Individual/Individual.js +++ b/src/containers/Individual/Individual.js @@ -49,19 +49,19 @@ class Individual extends Component { this.TABS = []; let { - user, + session, navigation: { state: { params: passProps } } } = this.props; - this.isLoginUser = !passProps || (+passProps.userId === user.authrization.uid); + this.isLoginUser = !passProps || (+passProps.userId === session.data.uid); if (this.isLoginUser) { let { - user: { - authrization: { + session: { + data: { uid, userName, avatar @@ -172,9 +172,9 @@ class Individual extends Component { } } -function mapStateToProps({ user, userTopicList }) { +function mapStateToProps({ session, userTopicList }) { return { - user, + session, userTopicList }; } diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index 787df28..6cbf9aa 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -8,7 +8,7 @@ import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import ImagePicker from '~/services/ImagePicker'; import MENUS from '~/constants/menus'; import api from '~/services/api'; -import { setAuthrization } from '~/actions/authorizeAction'; +import { setSession } from '~/common/modules/user/session.ducks'; import { fetchUser, resetUser } from '~/actions/user/userAction'; import mainStyles from '~/common/styles/Main.style'; @@ -39,8 +39,8 @@ class Information extends Component { uploadPhoto(image) { api.uploadAvatar(image).then(response => { // update redux store - this.props.setAuthrization({ - ...this.props.user.authrization, + this.props.setSession({ + ...this.props.session.data, avatar: response.data.pic_path }); // update storage @@ -115,9 +115,9 @@ class Information extends Component { } } -function mapStateToProps({ user, userItem }, ownProps) { +function mapStateToProps({ session, userItem }, ownProps) { return { - loginUserId: _.get(user, ['authrization', 'uid']), + loginUserId: _.get(session, ['data', 'uid']), userItem: _.get(userItem, ownProps.navigation.state.params.userId, {}) }; } diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index c777f4b..9a01449 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -13,11 +13,11 @@ import MenuItem from '~/components/MenuItem/MenuItem'; import MenuBottomItem from '~/components/MenuBottomItem/MenuBottomItem'; import MENUS from '~/constants/menus'; import { - userLogin, - resetAuthrization, - resetAuthrizationResult, - cleanCache -} from '~/actions/authorizeAction'; + login, + resetSession, + resetSessionResult, + logout +} from '~/common/modules/user/session.ducks'; import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; @@ -50,10 +50,10 @@ class Menu extends Component { } handleLogout() { - AsyncStorage.removeItem('authrization') + AsyncStorage.removeItem('session') .then(() => { // Remove all cache first. - this.props.cleanCache({ isLogin: false }); + this.props.logout({ isLogin: false }); // Back home page. this.props.navigation.dispatch(resetAction); }); @@ -61,9 +61,9 @@ class Menu extends Component { render() { let { - user: { - authrization, - authrization: { token } + session: { + data, + data: { token } }, alertCount } = this.props; @@ -76,7 +76,6 @@ class Menu extends Component { source={require('~/images/shahe.jpg')} style={styles.blur} /> {token && @@ -120,18 +119,18 @@ class Menu extends Component { } } -function mapStateToProps({ user, alert }) { +function mapStateToProps({ session, alert }) { return { - user, + session, alertCount: getAlertCount(alert) }; } export default connect(mapStateToProps, { - userLogin, - resetAuthrization, - resetAuthrizationResult, - cleanCache, + login, + resetSession, + resetSessionResult, + logout, invalidateTopicList, fetchTopicList })(Menu); diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index ef54cd6..2b96095 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -122,7 +122,7 @@ class Message extends Component { } } -function mapStateToProps({ notifyList, pmSessionList, alert, user }) { +function mapStateToProps({ notifyList, pmSessionList, alert, session }) { return { notifyList, pmSessionList, @@ -130,7 +130,7 @@ function mapStateToProps({ notifyList, pmSessionList, alert, user }) { replyCount: getReplyCount(alert), pmCount: getPmCount(alert), systemCount: getSystemCount(alert), - userId: _.get(user, ['authrization', 'uid']) + userId: _.get(session, ['data', 'uid']) }; } diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index 1a8a2b6..bd12b7f 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -21,7 +21,7 @@ import PublishModalScreen from '~/components/PublishModal/PublishModal'; import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; -import { getUserFromStorage } from '~/actions/authorizeAction'; +import { retrieveSessionFromStorage } from '~/common/modules/user/session.ducks'; import { retrieveSettingsFromStorage } from '~/common/modules/settings/settings.ducks'; import { fetchAlert } from '~/common/modules/message/alert.ducks'; import { ALERT_POLL_FREQUENCY } from '~/config'; @@ -131,13 +131,13 @@ class AppRoot extends Component { componentDidMount() { MessageBarManager.registerMessageBar(this.refs.alert); - this.props.getUserFromStorage(); + this.props.retrieveSessionFromStorage(); this.props.retrieveSettingsFromStorage(); } componentWillReceiveProps(nextProps) { - let currentToken = this.props.user.authrization.token; - let nextToken = nextProps.user.authrization.token; + let currentToken = this.props.session.data.token; + let nextToken = nextProps.session.data.token; let currentEnableNotification = this.props.settings.enableNotification; let nextEnableNotification = nextProps.settings.enableNotification; @@ -178,15 +178,15 @@ class AppRoot extends Component { } } -function mapStateToProps({ user, settings }) { +function mapStateToProps({ session, settings }) { return { - user, + session, settings }; } export default connect(mapStateToProps, { - getUserFromStorage, + retrieveSessionFromStorage, retrieveSettingsFromStorage, fetchAlert })(AppRoot); diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 0faff0a..5a33974 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -108,9 +108,9 @@ class Search extends Component { } } -function mapStateToProps({ searchList, user }) { +function mapStateToProps({ searchList, session }) { return { - userId: _.get(user, ['authrization', 'uid']), + userId: _.get(session, ['data', 'uid']), searchList }; } diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 3478d0a..e9e1ef4 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -96,7 +96,7 @@ class TopicDetail extends Component { // Use `headerTitle` here to avoid treating topic title // as screen header title. headerTitle: this.boardName, - isLogin: !!this.props.user.authrization.token, + isLogin: !!this.props.session.data.token, handleShowOperationDialog: () => this.showOperationDialog() }); this.fetchTopic(); @@ -170,8 +170,8 @@ class TopicDetail extends Component { topicItem: { topic }, - user: { - authrization: { uid } + session: { + data: { uid } } } = this.props; let { isFavoring, isVoting } = this.state; @@ -322,8 +322,8 @@ class TopicDetail extends Component { '复制链接' ]; let { - user: { - authrization: { uid } + session: { + data: { uid } }, topicItem: { topic: { @@ -400,8 +400,8 @@ class TopicDetail extends Component { } }, navigation, - user: { - authrization: { uid } + session: { + data: { uid } } } = this.props; @@ -458,11 +458,11 @@ class TopicDetail extends Component { } function mapStateToProps(state, ownProps) { - let { topicItem, user } = state; + let { topicItem, session } = state; return { topicItem: _.get(topicItem, getTopicId(ownProps.navigation.state.params), {}), - user + session }; } diff --git a/src/reducers/index.js b/src/reducers/index.js index 2b2e691..2c1e17c 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,5 +1,5 @@ import { combineReducers } from 'redux'; -import user from './user'; +import session from '~/common/modules/user/session.ducks'; import forumList from '~/common/modules/forum/forumList.ducks'; import topicList from '~/common/modules/topic/topicList.ducks'; import topicItem from '~/common/modules/topic/topic.ducks'; @@ -23,7 +23,7 @@ export default combineReducers({ send, alert, - user, + session, userItem, topicItem, searchList, diff --git a/src/reducers/user.js b/src/reducers/user.js deleted file mode 100644 index 1acc9a2..0000000 --- a/src/reducers/user.js +++ /dev/null @@ -1,61 +0,0 @@ -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - REQUEST_FAILED, - SET_AUTHRIZATION, - REMOVE_CACHE, - RESET_AUTHRIZATION, - RESET_AUTHRIZATION_RESULT -} from '~/actions/authorizeAction'; - -const defaultUserState = { - isFetching: false, - authrization: {}, - hasError: false, - result: false -}; - -export default function user(state = defaultUserState, action) { - switch (action.type) { - case SET_AUTHRIZATION: - return { - ...state, - authrization: action.payload - }; - case REQUEST_STARTED: - return { - ...state, - isFetching: true, - authrization: {}, - hasError: false, - result: false - }; - case REQUEST_COMPELTED: - return { - ...state, - isFetching: false, - authrization: action.payload, - hasError: !!action.payload.errcode, - result: !!action.payload.rs - }; - case REQUEST_FAILED: - return { - ...state, - isFetching: false - }; - case REMOVE_CACHE: - if (!action.payload.isLogin) { - return defaultUserState; - } - return state; - case RESET_AUTHRIZATION: - return defaultUserState; - case RESET_AUTHRIZATION_RESULT: - return { - ...state, - result: false - }; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 4593ae3..a3b94ea 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,7 +1,7 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; -import * as authorizeActions from '~/actions/authorizeAction'; +import * as sessionActions from '~/common/modules/user/session.ducks'; import * as topicListActions from '~/common/modules/topic/topicList.ducks'; import * as userTopicListActions from '~/common/modules/user/userTopicList.ducks'; import * as forumListActions from '~/common/modules/forum/forumList.ducks'; @@ -20,7 +20,7 @@ import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; -const fetchLoginUserApi = fetchResource.bind(null, authorizeActions, api.fetchLoginUser); +const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); const fetchTopicListApi = fetchResource.bind(null, topicListActions, api.fetchTopicList); const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchForumListApi = fetchResource.bind(null, forumListActions, api.fetchForumList); @@ -36,27 +36,27 @@ const fetchFriendListApi = fetchResource.bind(null, friendListActions, api.fetch // user login sagas -function* watchRetrieveUser() { +function* watchRetrieveSession() { while(true) { - yield take(authorizeActions.RETRIEVE); - const authrization = yield call(getUserFromStorage); + yield take(sessionActions.SESSION_RETRIEVE); + let session = yield call(retrieveSessionFromStorage); - if (authrization) { - const user = JSON.parse(authrization); - yield put(authorizeActions.setAuthrization(user)); + if (session) { + session = JSON.parse(session); + yield put(sessionActions.setSession(session)); } } } // how to use `yield` inside callback? // https://github.com/redux-saga/redux-saga/issues/508 -function getUserFromStorage() { - return new Promise(resolve => AsyncStorage.getItem('authrization').then(resolve)); +function retrieveSessionFromStorage() { + return new Promise(resolve => AsyncStorage.getItem('session').then(resolve)); } function* watchLogin() { while(true) { - const { payload } = yield take(authorizeActions.REQUEST); + const { payload } = yield take(sessionActions.LOGIN); yield fork(fetchLoginUserApi, payload); } } @@ -260,7 +260,7 @@ function* fetchFriendList(payload) { } export default function* rootSaga() { - yield fork(watchRetrieveUser); + yield fork(watchRetrieveSession); yield fork(watchLogin); yield fork(watchTopicList); yield fork(watchUserTopicList); diff --git a/src/utils/request.js b/src/utils/request.js index eb89c55..54765b0 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -34,10 +34,10 @@ function handleError(error) { } export default function request(url, options) { - return AsyncStorage.getItem('authrization') - .then(authrization => { - if (authrization) { - let { token, secret } = JSON.parse(authrization); + return AsyncStorage.getItem('session') + .then(session => { + if (session) { + let { token, secret } = JSON.parse(session); url += `&accessToken=${token}&accessSecret=${secret}`; } From 1c6a0abceafe89bcfc3f07ed2d3668eb1aad5b97 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 13 Aug 2018 15:21:30 +0800 Subject: [PATCH 15/58] refactor: introduce ducks pattern for user --- src/actions/index.js | 1 - src/actions/user/userAction.js | 14 ---- src/common/modules/user/user.ducks.js | 83 +++++++++++++++++++++++ src/containers/Information/Information.js | 2 +- src/reducers/index.js | 2 +- src/reducers/user/userItem.js | 70 ------------------- src/sagas/index.js | 4 +- 7 files changed, 87 insertions(+), 89 deletions(-) delete mode 100644 src/actions/index.js delete mode 100644 src/actions/user/userAction.js create mode 100644 src/common/modules/user/user.ducks.js delete mode 100644 src/reducers/user/userItem.js diff --git a/src/actions/index.js b/src/actions/index.js deleted file mode 100644 index 52a23df..0000000 --- a/src/actions/index.js +++ /dev/null @@ -1 +0,0 @@ -export userAction from './user/userAction'; diff --git a/src/actions/user/userAction.js b/src/actions/user/userAction.js deleted file mode 100644 index 3bb77d8..0000000 --- a/src/actions/user/userAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const fetchUser = createAction(REQUEST); -export const resetUser = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/common/modules/user/user.ducks.js b/src/common/modules/user/user.ducks.js new file mode 100644 index 0000000..3ecf31f --- /dev/null +++ b/src/common/modules/user/user.ducks.js @@ -0,0 +1,83 @@ +import { createAction, handleActions } from 'redux-actions'; +import _ from 'lodash'; + +// ********************************* +// Actions +// ********************************* + +export const USER_FETCH = 'USER_FETCH'; +export const USER_RESET = 'USER_RESET'; + +const USER_FETCH_REQUEST = 'USER_FETCH_REQUEST'; +const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'; +const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchUser = createAction(USER_FETCH); +export const resetUser = createAction(USER_RESET); + +export const request = createAction(USER_FETCH_REQUEST); +export const success = createAction(USER_FETCH_SUCCESS, null, (...args) => args[1]); +export const failure = createAction(USER_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultState = {}; +const defaultUserState = { + isFetching: false, + user: {}, + errCode: '' +}; + +export default handleActions({ + [USER_FETCH_REQUEST]: (state, action) => { + let { userId } = action.payload; + return { + ...state, + [userId]: { + isFetching: true, + ..._.get(state, userId, defaultUserState) + } + }; + }, + [USER_FETCH_SUCCESS]: (state, action) => { + let { + payload, + meta: { + userId + } + } = action; + return { + ...state, + [userId]: { + ..._.get(state, userId, defaultUserState), + isFetching: false, + user: payload, + errCode: payload.errcode + } + }; + }, + [USER_FETCH_FAILURE]: (state, action) => { + let { userId } = action.payload; + return { + ...state, + [userId]: { + isFetching: false, + ..._.get(state, userId, defaultUserState) + } + }; + }, + // We didn't cahce user item like topic list, because user information + // will be updated frequently like published/replied post count. + // + // This will be triggerd in `componentWillUnmount()`. + [USER_RESET]: (state, action) => { + let { userId } = action.payload; + return _.pickBy(state, (value, key) => +key !== userId); + } +}, defaultState); diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index 6cbf9aa..d6d8426 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -9,7 +9,7 @@ import ImagePicker from '~/services/ImagePicker'; import MENUS from '~/constants/menus'; import api from '~/services/api'; import { setSession } from '~/common/modules/user/session.ducks'; -import { fetchUser, resetUser } from '~/actions/user/userAction'; +import { fetchUser, resetUser } from '~/common/modules/user/user.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; diff --git a/src/reducers/index.js b/src/reducers/index.js index 2c1e17c..3e2495d 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -11,7 +11,7 @@ import pmList from '~/common/modules/message/pmList.ducks'; import send from './message/send'; import alert from '~/common/modules/message/alert.ducks'; import settings from '~/common/modules/settings/settings.ducks'; -import userItem from './user/userItem'; +import userItem from '~/common/modules/user/user.ducks'; import friendList from '~/common/modules/user/friendList.ducks'; export default combineReducers({ diff --git a/src/reducers/user/userItem.js b/src/reducers/user/userItem.js deleted file mode 100644 index 176230c..0000000 --- a/src/reducers/user/userItem.js +++ /dev/null @@ -1,70 +0,0 @@ -import _ from 'lodash'; -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - RESET, - REQUEST_FAILED -} from '~/actions/user/userAction'; - -const defaultState = {}; -const defaultUserState = { - isFetching: false, - user: {}, - errCode: '' -}; - -export default function userItem(state = defaultState, action) { - switch (action.type) { - case REQUEST_STARTED: { - let { userId } = action.payload; - - return { - ...state, - [userId]: { - isFetching: true, - ..._.get(state, userId, defaultUserState) - } - }; - } - case REQUEST_COMPELTED: { - let { - payload, - meta: { - userId - } - } = action; - - return { - ...state, - [userId]: { - ..._.get(state, userId, defaultUserState), - isFetching: false, - user: payload, - errCode: payload.errcode - } - }; - } - // We didn't cahce user item like topic list, because user information - // will be updated frequently like published/replied post count. - // - // This will be triggerd in `componentWillUnmount()`. - case RESET: { - let { userId } = action.payload; - - return _.pickBy(state, (value, key) => +key !== userId); - } - case REQUEST_FAILED: { - let { userId } = action.payload; - - return { - ...state, - [userId]: { - isFetching: false, - ..._.get(state, userId, defaultUserState) - } - }; - } - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index a3b94ea..14f7f3d 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -13,7 +13,7 @@ import * as pmListActions from '~/common/modules/message/pmList.ducks'; import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/common/modules/message/alert.ducks'; import * as settingsActions from '~/common/modules/settings/settings.ducks'; -import * as userActions from '~/actions/user/userAction'; +import * as userActions from '~/common/modules/user/user.ducks'; import * as friendListActions from '~/common/modules/user/friendList.ducks'; import cacheManager from '~/services/cacheManager'; @@ -237,7 +237,7 @@ function* watchAlerts() { function* watchUsers() { while(true) { - const { payload } = yield take(userActions.REQUEST); + const { payload } = yield take(userActions.USER_FETCH); yield fork(fetchUserApi, payload); } } From 0cdca415549597a08b088096d620668d928bd949 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 13 Aug 2018 17:57:00 +0800 Subject: [PATCH 16/58] refactor: replace redux state with local state for message sending --- src/actions/message/sendAction.js | 14 --- .../modules/root/rootReducer.js} | 28 +++--- src/containers/PmList/PmList.js | 95 +++++++++---------- src/reducers/message/send.js | 45 --------- src/sagas/index.js | 12 --- src/store/configureStore.js | 2 +- 6 files changed, 58 insertions(+), 138 deletions(-) delete mode 100644 src/actions/message/sendAction.js rename src/{reducers/index.js => common/modules/root/rootReducer.js} (96%) delete mode 100644 src/reducers/message/send.js diff --git a/src/actions/message/sendAction.js b/src/actions/message/sendAction.js deleted file mode 100644 index 3b11464..0000000 --- a/src/actions/message/sendAction.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction } from 'redux-actions'; - -export const REQUEST = Symbol(); -export const RESET = Symbol(); -export const submit = createAction(REQUEST); -export const resetPublish = createAction(RESET); - -export const REQUEST_STARTED = Symbol(); -export const REQUEST_COMPELTED = Symbol(); -export const REQUEST_FAILED = Symbol(); -export const request = createAction(REQUEST_STARTED); -// return 2nd argument as `meta` field -export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]); -export const failure = createAction(REQUEST_FAILED); diff --git a/src/reducers/index.js b/src/common/modules/root/rootReducer.js similarity index 96% rename from src/reducers/index.js rename to src/common/modules/root/rootReducer.js index 3e2495d..3b6467a 100644 --- a/src/reducers/index.js +++ b/src/common/modules/root/rootReducer.js @@ -1,35 +1,33 @@ import { combineReducers } from 'redux'; import session from '~/common/modules/user/session.ducks'; -import forumList from '~/common/modules/forum/forumList.ducks'; import topicList from '~/common/modules/topic/topicList.ducks'; -import topicItem from '~/common/modules/topic/topic.ducks'; +import forumList from '~/common/modules/forum/forumList.ducks'; import searchList from '~/common/modules/topic/searchList.ducks'; import notifyList from '~/common/modules/message/notifyList.ducks'; import pmSessionList from '~/common/modules/message/pmSessionList.ducks'; -import userTopicList from '~/common/modules/user/userTopicList.ducks'; import pmList from '~/common/modules/message/pmList.ducks'; -import send from './message/send'; +import userTopicList from '~/common/modules/user/userTopicList.ducks'; +import friendList from '~/common/modules/user/friendList.ducks'; +import topicItem from '~/common/modules/topic/topic.ducks'; +import userItem from '~/common/modules/user/user.ducks'; import alert from '~/common/modules/message/alert.ducks'; import settings from '~/common/modules/settings/settings.ducks'; -import userItem from '~/common/modules/user/user.ducks'; -import friendList from '~/common/modules/user/friendList.ducks'; export default combineReducers({ - forumList, + session, + topicList, + forumList, + searchList, notifyList, pmSessionList, pmList, - send, - alert, - - session, - userItem, - topicItem, - searchList, + userTopicList, friendList, - userTopicList, + topicItem, + userItem, + alert, settings }); diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index b54b797..e0387f5 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -12,16 +12,13 @@ import GiftedChatSendButton from '~/common/vendor/components/GiftedChatSendButto import GiftedChatLoadEarlierButton from '~/common/vendor/components/GiftedChatLoadEarlierButton'; import GiftedChatMessageText from '~/common/vendor/components/GiftedChatMessageText'; import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; -import { - submit, - resetPublish -} from '~/actions/message/sendAction'; import { fetchPmList, resetPmList, resetPmListResponseStatus } from '~/common/modules/message/pmList.ducks'; import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '~/config'; +import api from '~/services/api'; import mainStyles from '~/common/styles/Main.style'; import styles from './PmList.style'; @@ -42,7 +39,8 @@ class PmList extends Component { let { userId } = this.props.navigation.state.params; this.userId = userId; this.state = { - messages: [] + messages: [], + isPublishing: false }; } @@ -73,48 +71,16 @@ class PmList extends Component { } componentWillReceiveProps(nextProps) { - this.setUpTitle(nextProps.pmList.user.name); + let { pmList } = nextProps; + this.setUpTitle(pmList.user.name); // Handle private messages. - let { - send, - pmList - } = nextProps; + let { isPublishing } = this.state; - if (send.isPublishing) { return; } + if (isPublishing) { return; } if (pmList.isRefreshing) { return; } - if (send.response) { - let { rs, errcode } = send.response; - - if (rs) { - // This is workaround to fix #14. - // In produciton, sometimes the new sent message can not be displayed - // in bubble list even it has been sent successfully, but it's very - // hard to be reproduced in development mode. As we know, JavaScript - // thread performance suffers greatly when running in development mode, - // so the workaround can not only fix the weird issue here, but also can - // give user a better ux with customized ticks `发送中...`, which seems - // like the best solustion now. - setTimeout(() => { this.fetchPmList(); }, 1000 * 3); - } else if (errcode) { - // The time between sending two messages is too short. - this.fetchPmList(); - AlertIOS.alert('提示', send.response.errcode); - } else { - // No network. - this.setState(previousState => { - return { - messages: previousState.messages.filter(message => !message.isNew) - }; - }); - } - - this.props.resetPublish(); - return; - } - // Translation from Redux store props to component state. if (pmList.response && pmList.response.rs) { this.setState({ @@ -138,9 +104,39 @@ class PmList extends Component { }; }); - this.props.submit({ + this.setState({ isPublishing: true }); + api.sendMessage({ newMessage: messages[0], toUserId + }).then(response => { + if (response.error && response.error.message === 'Network request failed') { + // No network. + this.setState(previousState => { + return { + messages: previousState.messages.filter(message => !message.isNew) + }; + }); + return; + } + + let { rs, errcode } = response.data; + if (rs) { + // This is workaround to fix #14. + // In produciton, sometimes the new sent message can not be displayed + // in bubble list even it has been sent successfully, but it's very + // hard to be reproduced in development mode. As we know, JavaScript + // thread performance suffers greatly when running in development mode, + // so the workaround can not only fix the weird issue here, but also can + // give user a better ux with customized ticks `发送中...`, which seems + // like the best solution now. + setTimeout(() => { this.fetchPmList(); }, 1000 * 3); + } else if (errcode) { + // The time between sending two messages is too short. + this.fetchPmList(); + AlertIOS.alert('提示', errcode); + } + }).finally(() => { + this.setState({ isPublishing: false }); }); } @@ -152,9 +148,9 @@ class PmList extends Component { hasPrev, user, page - }, - send + } } = this.props; + let { isPublishing } = this.state; if (isRefreshing && page === 0) { return ( @@ -200,7 +196,7 @@ class PmList extends Component { return ( - {send.isPublishing && 发布中...} + {isPublishing && 发布中...} ); }} @@ -211,17 +207,14 @@ class PmList extends Component { } } -function mapStateToProps({ pmList, send }) { +function mapStateToProps({ pmList }) { return { - pmList, - send + pmList }; } export default connect(mapStateToProps, { fetchPmList, resetPmList, - resetPmListResponseStatus, - submit, - resetPublish + resetPmListResponseStatus })(PmList); diff --git a/src/reducers/message/send.js b/src/reducers/message/send.js deleted file mode 100644 index 86e4212..0000000 --- a/src/reducers/message/send.js +++ /dev/null @@ -1,45 +0,0 @@ -import { - REQUEST_STARTED, - REQUEST_COMPELTED, - RESET, - REQUEST_FAILED -} from '~/actions/message/sendAction'; - -const defaultState = { - isPublishing: false, - response: '' -}; - -export default function publish(state = defaultState, action) { - switch (action.type) { - case REQUEST_STARTED: - return { - ...state, - isPublishing: true - }; - case REQUEST_COMPELTED: - return { - ...state, - isPublishing: false, - response: action.payload - }; - case REQUEST_FAILED: - // if the time between sending two messages is too short, - // the action will be `REQUEST_COMPELTED` with response - // { rs: 0, errocde: '两次发送短消息太快,请稍后再发送' }, - // so we set `errocde` to empty here to distinguish no - // network or other failed situation from it. - return { - ...state, - isPublishing: false, - response: { - rs: 0, - errcode: '' - } - }; - case RESET: - return defaultState; - default: - return state; - } -} diff --git a/src/sagas/index.js b/src/sagas/index.js index 14f7f3d..c1519d3 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -10,7 +10,6 @@ import * as searchListActions from '~/common/modules/topic/searchList.ducks'; import * as topicActions from '~/common/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/common/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/common/modules/message/pmList.ducks'; -import * as sendActions from '~/actions/message/sendAction'; import * as alertActions from '~/common/modules/message/alert.ducks'; import * as settingsActions from '~/common/modules/settings/settings.ducks'; import * as userActions from '~/common/modules/user/user.ducks'; @@ -29,7 +28,6 @@ const fetchSearchListApi = fetchResource.bind(null, searchListActions, api.fetch const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); -const sendMessageApi = fetchResource.bind(null, sendActions, api.sendMessage); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); const fetchUserApi = fetchResource.bind(null, userActions, api.fetchUser); const fetchFriendListApi = fetchResource.bind(null, friendListActions, api.fetchFriendList); @@ -215,15 +213,6 @@ function* watchPmList() { } } -// send pm sagas - -function* watchSendMessage() { - while(true) { - const { payload } = yield take(sendActions.REQUEST); - yield fork(sendMessageApi, payload); - } -} - // alerts sagas function* watchAlerts() { @@ -270,7 +259,6 @@ export default function* rootSaga() { yield fork(watchTopic); yield fork(watchPmSessionList); yield fork(watchPmList); - yield fork(watchSendMessage); yield fork(watchAlerts); yield fork(watchRetrieveSettings); yield fork(watchStoreSettings); diff --git a/src/store/configureStore.js b/src/store/configureStore.js index 27ba6ad..c0d461e 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,6 +1,6 @@ import { createStore, applyMiddleware, compose } from 'redux'; import createSagaMiddleware from 'redux-saga'; -import rootReducer from '~/reducers'; +import rootReducer from '~/common/modules/root/rootReducer'; const sagaMiddleware = createSagaMiddleware(); From b06b838915c65559a49ebd21d01b49ba68714d32 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 13 Aug 2018 18:02:06 +0800 Subject: [PATCH 17/58] refactor: move `modules` to root --- src/common/modules/root/rootReducer.js | 33 ------------------- .../ForumListModal/ForumListModal.js | 2 +- .../FriendListModal/FriendListModal.js | 2 +- src/components/LoginModal/LoginModal.js | 2 +- src/components/PublishModal/PublishModal.js | 2 +- src/components/ReplyModal/ReplyModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 4 +-- src/containers/ForumList/ForumList.js | 2 +- src/containers/Home/Home.js | 2 +- src/containers/Individual/Individual.js | 2 +- src/containers/Information/Information.js | 4 +-- src/containers/Menu/Menu.js | 4 +-- src/containers/Message/Message.js | 4 +-- src/containers/Navigator/Navigator.js | 6 ++-- src/containers/PmList/PmList.js | 2 +- src/containers/Search/Search.js | 2 +- src/containers/Settings/Settings.js | 4 +-- src/containers/TopicDetail/TopicDetail.js | 2 +- .../modules/forum/forumList.ducks.js | 2 +- .../modules/message/alert.ducks.js | 6 ++-- .../modules/message/notifyList.ducks.js | 2 +- .../modules/message/pmList.ducks.js | 0 .../modules/message/pmSessionList.ducks.js | 2 +- src/modules/root/rootReducer.js | 33 +++++++++++++++++++ .../modules/settings/settings.ducks.js | 0 .../modules/topic/searchList.ducks.js | 0 src/{common => }/modules/topic/topic.ducks.js | 0 .../modules/topic/topicList.ducks.js | 2 +- .../modules/user/friendList.ducks.js | 0 .../modules/user/session.ducks.js | 0 src/{common => }/modules/user/user.ducks.js | 0 .../modules/user/userTopicList.ducks.js | 2 +- src/sagas/index.js | 26 +++++++-------- src/store/configureStore.js | 2 +- 34 files changed, 79 insertions(+), 79 deletions(-) delete mode 100644 src/common/modules/root/rootReducer.js rename src/{common => }/modules/forum/forumList.ducks.js (97%) rename src/{common => }/modules/message/alert.ducks.js (92%) rename src/{common => }/modules/message/notifyList.ducks.js (98%) rename src/{common => }/modules/message/pmList.ducks.js (100%) rename src/{common => }/modules/message/pmSessionList.ducks.js (97%) create mode 100644 src/modules/root/rootReducer.js rename src/{common => }/modules/settings/settings.ducks.js (100%) rename src/{common => }/modules/topic/searchList.ducks.js (100%) rename src/{common => }/modules/topic/topic.ducks.js (100%) rename src/{common => }/modules/topic/topicList.ducks.js (98%) rename src/{common => }/modules/user/friendList.ducks.js (100%) rename src/{common => }/modules/user/session.ducks.js (100%) rename src/{common => }/modules/user/user.ducks.js (100%) rename src/{common => }/modules/user/userTopicList.ducks.js (98%) diff --git a/src/common/modules/root/rootReducer.js b/src/common/modules/root/rootReducer.js deleted file mode 100644 index 3b6467a..0000000 --- a/src/common/modules/root/rootReducer.js +++ /dev/null @@ -1,33 +0,0 @@ -import { combineReducers } from 'redux'; -import session from '~/common/modules/user/session.ducks'; -import topicList from '~/common/modules/topic/topicList.ducks'; -import forumList from '~/common/modules/forum/forumList.ducks'; -import searchList from '~/common/modules/topic/searchList.ducks'; -import notifyList from '~/common/modules/message/notifyList.ducks'; -import pmSessionList from '~/common/modules/message/pmSessionList.ducks'; -import pmList from '~/common/modules/message/pmList.ducks'; -import userTopicList from '~/common/modules/user/userTopicList.ducks'; -import friendList from '~/common/modules/user/friendList.ducks'; -import topicItem from '~/common/modules/topic/topic.ducks'; -import userItem from '~/common/modules/user/user.ducks'; -import alert from '~/common/modules/message/alert.ducks'; -import settings from '~/common/modules/settings/settings.ducks'; - -export default combineReducers({ - session, - - topicList, - forumList, - searchList, - notifyList, - pmSessionList, - pmList, - userTopicList, - friendList, - - topicItem, - userItem, - - alert, - settings -}); diff --git a/src/components/ForumListModal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js index dd02f9d..b595246 100644 --- a/src/components/ForumListModal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import Header from '~/components/Header/Header'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/components/FriendListModal/FriendListModal.js b/src/components/FriendListModal/FriendListModal.js index 0f3e3ee..3f9eaba 100644 --- a/src/components/FriendListModal/FriendListModal.js +++ b/src/components/FriendListModal/FriendListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import FriendList from '~/components/FriendList/FriendList'; import Header from '~/components/Header/Header'; -import { invalidateFriendList, fetchFriendList } from '~/common/modules/user/friendList.ducks'; +import { invalidateFriendList, fetchFriendList } from '~/modules/user/friendList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/components/LoginModal/LoginModal.js b/src/components/LoginModal/LoginModal.js index bc03b29..eb3ce45 100644 --- a/src/components/LoginModal/LoginModal.js +++ b/src/components/LoginModal/LoginModal.js @@ -23,7 +23,7 @@ import { resetSession, resetSessionResult, logout -} from '~/common/modules/user/session.ducks'; +} from '~/modules/user/session.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from './LoginModal.style'; diff --git a/src/components/PublishModal/PublishModal.js b/src/components/PublishModal/PublishModal.js index 8d8def8..234e83a 100644 --- a/src/components/PublishModal/PublishModal.js +++ b/src/components/PublishModal/PublishModal.js @@ -24,7 +24,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/components/ReplyModal/ReplyModal.js b/src/components/ReplyModal/ReplyModal.js index fd2ac94..334e7aa 100644 --- a/src/components/ReplyModal/ReplyModal.js +++ b/src/components/ReplyModal/ReplyModal.js @@ -19,7 +19,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { fetchTopic } from '~/common/modules/topic/topic.ducks'; +import { fetchTopic } from '~/modules/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 700164e..97f217b 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -11,8 +11,8 @@ import TopicList from '~/components/TopicList/TopicList'; import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/common/modules/topic/topicList.ducks'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; +import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index 5257d6c..f129aa8 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -8,7 +8,7 @@ import { import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import MENUS from '~/constants/menus'; -import { invalidateForumList, fetchForumList } from '~/common/modules/forum/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index 0d639e6..afc5088 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -10,7 +10,7 @@ import Header from '~/components/Header/Header'; import TopicList from '~/components/TopicList/TopicList'; import MenuButton from '~/components/MenuButton/MenuButton'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/Individual/Individual.js b/src/containers/Individual/Individual.js index 8f9ee50..117893b 100644 --- a/src/containers/Individual/Individual.js +++ b/src/containers/Individual/Individual.js @@ -12,7 +12,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import { HeaderBackButton } from 'react-navigation'; import TopicList from '~/components/TopicList/TopicList'; -import { invalidateUserTopicList, fetchUserTopicList } from '~/common/modules/user/userTopicList.ducks'; +import { invalidateUserTopicList, fetchUserTopicList } from '~/modules/user/userTopicList.ducks'; import { AVATAR_ROOT } from '~/config'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index d6d8426..d450f97 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -8,8 +8,8 @@ import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import ImagePicker from '~/services/ImagePicker'; import MENUS from '~/constants/menus'; import api from '~/services/api'; -import { setSession } from '~/common/modules/user/session.ducks'; -import { fetchUser, resetUser } from '~/common/modules/user/user.ducks'; +import { setSession } from '~/modules/user/session.ducks'; +import { fetchUser, resetUser } from '~/modules/user/user.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index 9a01449..74d113f 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -17,8 +17,8 @@ import { resetSession, resetSessionResult, logout -} from '~/common/modules/user/session.ducks'; -import { invalidateTopicList, fetchTopicList } from '~/common/modules/topic/topicList.ducks'; +} from '~/modules/user/session.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import styles from './Menu.style'; diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index 2b96095..ef32e21 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -8,8 +8,8 @@ import NotifyList from '~/components/NotifyList/NotifyList'; import PmSessionList from '~/components/PmSessionList/PmSessionList'; import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; -import { invalidateNotifyList, fetchNotifyList } from '~/common/modules/message/notifyList.ducks'; -import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/common/modules/message/pmSessionList.ducks'; +import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList.ducks'; +import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList.ducks'; import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index bd12b7f..712792d 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -21,9 +21,9 @@ import PublishModalScreen from '~/components/PublishModal/PublishModal'; import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; -import { retrieveSessionFromStorage } from '~/common/modules/user/session.ducks'; -import { retrieveSettingsFromStorage } from '~/common/modules/settings/settings.ducks'; -import { fetchAlert } from '~/common/modules/message/alert.ducks'; +import { retrieveSessionFromStorage } from '~/modules/user/session.ducks'; +import { retrieveSettingsFromStorage } from '~/modules/settings/settings.ducks'; +import { fetchAlert } from '~/modules/message/alert.ducks'; import { ALERT_POLL_FREQUENCY } from '~/config'; import colors from '~/common/styles/colors.style'; diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index e0387f5..8dbfe00 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -16,7 +16,7 @@ import { fetchPmList, resetPmList, resetPmListResponseStatus -} from '~/common/modules/message/pmList.ducks'; +} from '~/modules/message/pmList.ducks'; import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '~/config'; import api from '~/services/api'; diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 5a33974..b1fe8a5 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -9,7 +9,7 @@ import SearchBar from 'react-native-search-bar'; import TopicList from '~/components/TopicList/TopicList'; import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import MENUS from '~/constants/menus'; -import { fetchSearchList, resetSearchList } from '~/common/modules/topic/searchList.ducks'; +import { fetchSearchList, resetSearchList } from '~/modules/topic/searchList.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 23421a0..8d594a6 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -13,8 +13,8 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; -import { retrieveSettingsFromStorage, storeSettingsToStorage } from '~/common/modules/settings/settings.ducks'; -import { resetAlert } from '~/common/modules/message/alert.ducks'; +import { retrieveSettingsFromStorage, storeSettingsToStorage } from '~/modules/settings/settings.ducks'; +import { resetAlert } from '~/modules/message/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from '~/containers/Settings/Settings.style'; diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index e9e1ef4..edeb5d9 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -27,7 +27,7 @@ import SafariView from '~/services/SafariView'; import api from '~/services/api'; import { TOPIC_URL_ROOT } from '~/config'; import { parseContentWithEmoji } from '~/utils/contentParser'; -import { fetchTopic, resetTopic } from '~/common/modules/topic/topic.ducks'; +import { fetchTopic, resetTopic } from '~/modules/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; diff --git a/src/common/modules/forum/forumList.ducks.js b/src/modules/forum/forumList.ducks.js similarity index 97% rename from src/common/modules/forum/forumList.ducks.js rename to src/modules/forum/forumList.ducks.js index c0ac53d..7c3d50d 100644 --- a/src/common/modules/forum/forumList.ducks.js +++ b/src/modules/forum/forumList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; import _ from 'lodash'; // ********************************* diff --git a/src/common/modules/message/alert.ducks.js b/src/modules/message/alert.ducks.js similarity index 92% rename from src/common/modules/message/alert.ducks.js rename to src/modules/message/alert.ducks.js index 99b12f2..e98435a 100644 --- a/src/common/modules/message/alert.ducks.js +++ b/src/modules/message/alert.ducks.js @@ -4,9 +4,9 @@ import { MARK_AT_ME_AS_READ, MARK_REPLY_AS_READ, MARK_SYSTEM_AS_READ -} from '~/common/modules/message/notifyList.ducks'; -import { MARK_PM_AS_READ } from '~/common/modules/message/pmSessionList.ducks'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +} from '~/modules/message/notifyList.ducks'; +import { MARK_PM_AS_READ } from '~/modules/message/pmSessionList.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; // ********************************* // Actions diff --git a/src/common/modules/message/notifyList.ducks.js b/src/modules/message/notifyList.ducks.js similarity index 98% rename from src/common/modules/message/notifyList.ducks.js rename to src/modules/message/notifyList.ducks.js index 2dd9e21..806924b 100644 --- a/src/common/modules/message/notifyList.ducks.js +++ b/src/modules/message/notifyList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; // ********************************* // Actions diff --git a/src/common/modules/message/pmList.ducks.js b/src/modules/message/pmList.ducks.js similarity index 100% rename from src/common/modules/message/pmList.ducks.js rename to src/modules/message/pmList.ducks.js diff --git a/src/common/modules/message/pmSessionList.ducks.js b/src/modules/message/pmSessionList.ducks.js similarity index 97% rename from src/common/modules/message/pmSessionList.ducks.js rename to src/modules/message/pmSessionList.ducks.js index 67623d5..fe9f316 100644 --- a/src/common/modules/message/pmSessionList.ducks.js +++ b/src/modules/message/pmSessionList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; // ********************************* // Actions diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js new file mode 100644 index 0000000..2a476d6 --- /dev/null +++ b/src/modules/root/rootReducer.js @@ -0,0 +1,33 @@ +import { combineReducers } from 'redux'; +import session from '~/modules/user/session.ducks'; +import topicList from '~/modules/topic/topicList.ducks'; +import forumList from '~/modules/forum/forumList.ducks'; +import searchList from '~/modules/topic/searchList.ducks'; +import notifyList from '~/modules/message/notifyList.ducks'; +import pmSessionList from '~/modules/message/pmSessionList.ducks'; +import pmList from '~/modules/message/pmList.ducks'; +import userTopicList from '~/modules/user/userTopicList.ducks'; +import friendList from '~/modules/user/friendList.ducks'; +import topicItem from '~/modules/topic/topic.ducks'; +import userItem from '~/modules/user/user.ducks'; +import alert from '~/modules/message/alert.ducks'; +import settings from '~/modules/settings/settings.ducks'; + +export default combineReducers({ + session, + + topicList, + forumList, + searchList, + notifyList, + pmSessionList, + pmList, + userTopicList, + friendList, + + topicItem, + userItem, + + alert, + settings +}); diff --git a/src/common/modules/settings/settings.ducks.js b/src/modules/settings/settings.ducks.js similarity index 100% rename from src/common/modules/settings/settings.ducks.js rename to src/modules/settings/settings.ducks.js diff --git a/src/common/modules/topic/searchList.ducks.js b/src/modules/topic/searchList.ducks.js similarity index 100% rename from src/common/modules/topic/searchList.ducks.js rename to src/modules/topic/searchList.ducks.js diff --git a/src/common/modules/topic/topic.ducks.js b/src/modules/topic/topic.ducks.js similarity index 100% rename from src/common/modules/topic/topic.ducks.js rename to src/modules/topic/topic.ducks.js diff --git a/src/common/modules/topic/topicList.ducks.js b/src/modules/topic/topicList.ducks.js similarity index 98% rename from src/common/modules/topic/topicList.ducks.js rename to src/modules/topic/topicList.ducks.js index 321c60c..a7d08cd 100644 --- a/src/common/modules/topic/topicList.ducks.js +++ b/src/modules/topic/topicList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; import _ from 'lodash'; // ********************************* diff --git a/src/common/modules/user/friendList.ducks.js b/src/modules/user/friendList.ducks.js similarity index 100% rename from src/common/modules/user/friendList.ducks.js rename to src/modules/user/friendList.ducks.js diff --git a/src/common/modules/user/session.ducks.js b/src/modules/user/session.ducks.js similarity index 100% rename from src/common/modules/user/session.ducks.js rename to src/modules/user/session.ducks.js diff --git a/src/common/modules/user/user.ducks.js b/src/modules/user/user.ducks.js similarity index 100% rename from src/common/modules/user/user.ducks.js rename to src/modules/user/user.ducks.js diff --git a/src/common/modules/user/userTopicList.ducks.js b/src/modules/user/userTopicList.ducks.js similarity index 98% rename from src/common/modules/user/userTopicList.ducks.js rename to src/modules/user/userTopicList.ducks.js index d6e50bc..6660827 100644 --- a/src/common/modules/user/userTopicList.ducks.js +++ b/src/modules/user/userTopicList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/common/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session.ducks'; // ********************************* // Actions diff --git a/src/sagas/index.js b/src/sagas/index.js index c1519d3..62dca7a 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,19 +1,19 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; -import * as sessionActions from '~/common/modules/user/session.ducks'; -import * as topicListActions from '~/common/modules/topic/topicList.ducks'; -import * as userTopicListActions from '~/common/modules/user/userTopicList.ducks'; -import * as forumListActions from '~/common/modules/forum/forumList.ducks'; -import * as notifyListActions from '~/common/modules/message/notifyList.ducks'; -import * as searchListActions from '~/common/modules/topic/searchList.ducks'; -import * as topicActions from '~/common/modules/topic/topic.ducks'; -import * as pmSessionListActions from '~/common/modules/message/pmSessionList.ducks'; -import * as pmListActions from '~/common/modules/message/pmList.ducks'; -import * as alertActions from '~/common/modules/message/alert.ducks'; -import * as settingsActions from '~/common/modules/settings/settings.ducks'; -import * as userActions from '~/common/modules/user/user.ducks'; -import * as friendListActions from '~/common/modules/user/friendList.ducks'; +import * as sessionActions from '~/modules/user/session.ducks'; +import * as topicListActions from '~/modules/topic/topicList.ducks'; +import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; +import * as forumListActions from '~/modules/forum/forumList.ducks'; +import * as notifyListActions from '~/modules/message/notifyList.ducks'; +import * as searchListActions from '~/modules/topic/searchList.ducks'; +import * as topicActions from '~/modules/topic/topic.ducks'; +import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; +import * as pmListActions from '~/modules/message/pmList.ducks'; +import * as alertActions from '~/modules/message/alert.ducks'; +import * as settingsActions from '~/modules/settings/settings.ducks'; +import * as userActions from '~/modules/user/user.ducks'; +import * as friendListActions from '~/modules/user/friendList.ducks'; import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; diff --git a/src/store/configureStore.js b/src/store/configureStore.js index c0d461e..84c5b2f 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,6 +1,6 @@ import { createStore, applyMiddleware, compose } from 'redux'; import createSagaMiddleware from 'redux-saga'; -import rootReducer from '~/common/modules/root/rootReducer'; +import rootReducer from '~/modules/root/rootReducer'; const sagaMiddleware = createSagaMiddleware(); From 44391482eff4a8c0ef0808f31767768d064d977d Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 20 Aug 2018 01:13:48 +0800 Subject: [PATCH 18/58] refactor: replace redux-saga with redux-observable for topic list --- package.json | 4 ++- src/components/PublishModal/PublishModal.js | 2 +- src/containers/App/App.js | 2 ++ src/containers/ForumDetail/ForumDetail.js | 2 +- src/containers/Home/Home.js | 2 +- src/containers/Menu/Menu.js | 2 +- src/modules/root/rootEpic.js | 6 ++++ src/modules/root/rootReducer.js | 2 +- .../topic/{ => topicList}/topicList.ducks.js | 8 ++--- .../topic/topicList/topicList.epics.js | 30 +++++++++++++++++++ src/sagas/index.js | 21 ------------- src/store/configureStore.js | 6 +++- yarn.lock | 14 +++++++++ 13 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 src/modules/root/rootEpic.js rename src/modules/topic/{ => topicList}/topicList.ducks.js (92%) create mode 100644 src/modules/topic/topicList/topicList.epics.js diff --git a/package.json b/package.json index 8ea7b80..1e6dace 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,9 @@ "react-redux": "5.0.6", "redux": "3.3.1", "redux-actions": "1.2.1", - "redux-saga": "0.12.0" + "redux-observable": "^1.0.0", + "redux-saga": "0.12.0", + "rxjs": "^6.2.2" }, "devDependencies": { "babel": "^6.23.0", diff --git a/src/components/PublishModal/PublishModal.js b/src/components/PublishModal/PublishModal.js index 234e83a..92e580b 100644 --- a/src/components/PublishModal/PublishModal.js +++ b/src/components/PublishModal/PublishModal.js @@ -24,7 +24,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/App/App.js b/src/containers/App/App.js index 15c2ccb..58f6734 100644 --- a/src/containers/App/App.js +++ b/src/containers/App/App.js @@ -2,10 +2,12 @@ import React, { Component } from 'react'; import { Provider } from 'react-redux'; import configureStore from '~/store/configureStore'; import rootSaga from '~/sagas'; +import rootEpic from '~/modules/root/rootEpic'; import Navigator from '~/containers/Navigator/Navigator'; const store = configureStore(); store.runSaga(rootSaga); +store.runEpic(rootEpic); export default class App extends Component { render() { diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 97f217b..217e2e1 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -11,7 +11,7 @@ import TopicList from '~/components/TopicList/TopicList'; import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList/topicList.ducks'; import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index afc5088..097b717 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -10,7 +10,7 @@ import Header from '~/components/Header/Header'; import TopicList from '~/components/TopicList/TopicList'; import MenuButton from '~/components/MenuButton/MenuButton'; import PublishButton from '~/components/PublishButton/PublishButton'; -import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index 74d113f..c868d8d 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -18,7 +18,7 @@ import { resetSessionResult, logout } from '~/modules/user/session.ducks'; -import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList.ducks'; +import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; import styles from './Menu.style'; diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js new file mode 100644 index 0000000..7e48874 --- /dev/null +++ b/src/modules/root/rootEpic.js @@ -0,0 +1,6 @@ +import { combineEpics } from 'redux-observable'; +import topicList from '~/modules/topic/topicList/topicList.epics'; + +export default combineEpics( + topicList +); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 2a476d6..473fed3 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -1,6 +1,6 @@ import { combineReducers } from 'redux'; import session from '~/modules/user/session.ducks'; -import topicList from '~/modules/topic/topicList.ducks'; +import topicList from '~/modules/topic/topicList/topicList.ducks'; import forumList from '~/modules/forum/forumList.ducks'; import searchList from '~/modules/topic/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; diff --git a/src/modules/topic/topicList.ducks.js b/src/modules/topic/topicList/topicList.ducks.js similarity index 92% rename from src/modules/topic/topicList.ducks.js rename to src/modules/topic/topicList/topicList.ducks.js index a7d08cd..526760a 100644 --- a/src/modules/topic/topicList.ducks.js +++ b/src/modules/topic/topicList/topicList.ducks.js @@ -10,7 +10,6 @@ export const TOPIC_LIST_FETCH = 'TOPIC_LIST_FETCH'; export const TOPIC_LIST_INVALIDATE = 'TOPIC_LIST_INVALIDATE'; export const TOPIC_LIST_RESET = 'TOPIC_LIST_RESET'; -const TOPIC_LIST_FETCH_REQUEST = 'TOPIC_LIST_FETCH_REQUEST'; const TOPIC_LIST_FETCH_SUCCESS = 'TOPIC_LIST_FETCH_SUCCESS'; const TOPIC_LIST_FETCH_FAILURE = 'TOPIC_LIST_FETCH_FAILURE'; @@ -22,9 +21,8 @@ export const fetchTopicList = createAction(TOPIC_LIST_FETCH); export const invalidateTopicList = createAction(TOPIC_LIST_INVALIDATE); export const resetTopicList = createAction(TOPIC_LIST_RESET); -export const request = createAction(TOPIC_LIST_FETCH_REQUEST); -export const success = createAction(TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); +export const fetchTopicListSuccess = createAction(TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchTopicListFailure = createAction(TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); // ********************************* // Reducer @@ -58,7 +56,7 @@ export default handleActions({ } }; }, - [TOPIC_LIST_FETCH_REQUEST]: (state, action) => { + [TOPIC_LIST_FETCH]: (state, action) => { let { boardId, sortType, isEndReached } = action.payload; return { ...state, diff --git a/src/modules/topic/topicList/topicList.epics.js b/src/modules/topic/topicList/topicList.epics.js new file mode 100644 index 0000000..c51e4d0 --- /dev/null +++ b/src/modules/topic/topicList/topicList.epics.js @@ -0,0 +1,30 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { mergeMap, map } from 'rxjs/operators'; +import { + TOPIC_LIST_FETCH, + fetchTopicListSuccess, + fetchTopicListFailure +} from './topicList.ducks'; +import api from '~/services/api'; + +const fetchTopicList = (action$) => { + return action$.pipe( + ofType(TOPIC_LIST_FETCH), + mergeMap(action => api.fetchTopicList(action.payload) + .then(({ + data, + error + }) => { + if (!error) { + return fetchTopicListSuccess(data, action.payload); + } else { + return fetchTopicListFailure(error, action.payload); + } + }) + ) + ); +}; + +export default combineEpics( + fetchTopicList +); diff --git a/src/sagas/index.js b/src/sagas/index.js index 62dca7a..6b321ec 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,7 +2,6 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as sessionActions from '~/modules/user/session.ducks'; -import * as topicListActions from '~/modules/topic/topicList.ducks'; import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; import * as forumListActions from '~/modules/forum/forumList.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; @@ -20,7 +19,6 @@ import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); -const fetchTopicListApi = fetchResource.bind(null, topicListActions, api.fetchTopicList); const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchForumListApi = fetchResource.bind(null, forumListActions, api.fetchForumList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); @@ -95,24 +93,6 @@ function storeSettingsToStorage(settings) { return new Promise(resolve => AsyncStorage.setItem('settings', settings).then(resolve)); } -// topic list sagas - -function* watchTopicList() { - while(true) { - const { payload } = yield take(topicListActions.TOPIC_LIST_FETCH); - yield fork(fetchTopicList, payload); - } -} - -function* fetchTopicList(payload) { - const state = yield select(); - const { boardId, sortType } = payload; - - if (cacheManager.shouldFetchList(state, 'topicList', boardId, sortType)) { - yield fork(fetchTopicListApi, payload); - } -} - // user topic list sags function* watchUserTopicList() { @@ -251,7 +231,6 @@ function* fetchFriendList(payload) { export default function* rootSaga() { yield fork(watchRetrieveSession); yield fork(watchLogin); - yield fork(watchTopicList); yield fork(watchUserTopicList); yield fork(watchForumList); yield fork(watchNotifyList); diff --git a/src/store/configureStore.js b/src/store/configureStore.js index 84c5b2f..cfa4f92 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,12 +1,15 @@ import { createStore, applyMiddleware, compose } from 'redux'; import createSagaMiddleware from 'redux-saga'; +import { createEpicMiddleware } from 'redux-observable'; import rootReducer from '~/modules/root/rootReducer'; const sagaMiddleware = createSagaMiddleware(); +const epicMiddleware = createEpicMiddleware(); export default function configureStore(initialState = {}) { const middlewares = [ - sagaMiddleware + sagaMiddleware, + epicMiddleware ]; const enhancers = [ @@ -20,6 +23,7 @@ export default function configureStore(initialState = {}) { ); store.runSaga = sagaMiddleware.run; + store.runEpic = epicMiddleware.run; return store; } diff --git a/yarn.lock b/yarn.lock index 69f56c9..7dbfe45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4206,6 +4206,10 @@ redux-actions@1.2.1: lodash "^4.13.1" reduce-reducers "^0.1.0" +redux-observable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91" + redux-saga@0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.12.0.tgz#4b6145e6f8c33a6082f7d18f30ab5d2901e621e8" @@ -4406,6 +4410,12 @@ rxjs@^5.5.2: dependencies: symbol-observable "1.0.1" +rxjs@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.2.tgz#eb75fa3c186ff5289907d06483a77884586e1cf9" + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -4883,6 +4893,10 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + tsscmp@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" From bfb03984de08646eb92f5fa92c3f8638840e596b Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 26 Aug 2018 10:39:52 +0800 Subject: [PATCH 19/58] refactor: replace redux-saga with redux-observable for search list --- src/containers/Search/Search.js | 2 +- src/modules/root/rootEpic.js | 4 ++- src/modules/root/rootReducer.js | 2 +- .../{ => searchList}/searchList.ducks.js | 26 +++++++------- .../topic/searchList/searchList.epics.js | 28 +++++++++++++++ .../topic/topicList/topicList.ducks.js | 30 ++++++++-------- .../topic/topicList/topicList.epics.js | 34 +++++++++---------- src/sagas/index.js | 12 ------- 8 files changed, 76 insertions(+), 62 deletions(-) rename src/modules/topic/{ => searchList}/searchList.ducks.js (60%) create mode 100644 src/modules/topic/searchList/searchList.epics.js diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index b1fe8a5..9a0cf7b 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -9,7 +9,7 @@ import SearchBar from 'react-native-search-bar'; import TopicList from '~/components/TopicList/TopicList'; import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import MENUS from '~/constants/menus'; -import { fetchSearchList, resetSearchList } from '~/modules/topic/searchList.ducks'; +import { fetchSearchList, resetSearchList } from '~/modules/topic/searchList/searchList.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 7e48874..69355c2 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -1,6 +1,8 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; +import searchList from '~/modules/topic/searchList/searchList.epics'; export default combineEpics( - topicList + topicList, + searchList ); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 473fed3..b4af231 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -2,7 +2,7 @@ import { combineReducers } from 'redux'; import session from '~/modules/user/session.ducks'; import topicList from '~/modules/topic/topicList/topicList.ducks'; import forumList from '~/modules/forum/forumList.ducks'; -import searchList from '~/modules/topic/searchList.ducks'; +import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList.ducks'; import pmList from '~/modules/message/pmList.ducks'; diff --git a/src/modules/topic/searchList.ducks.js b/src/modules/topic/searchList/searchList.ducks.js similarity index 60% rename from src/modules/topic/searchList.ducks.js rename to src/modules/topic/searchList/searchList.ducks.js index 8dc2cf6..7724498 100644 --- a/src/modules/topic/searchList.ducks.js +++ b/src/modules/topic/searchList/searchList.ducks.js @@ -4,23 +4,21 @@ import { createAction, handleActions } from 'redux-actions'; // Actions // ********************************* -export const SEARCH_LIST_FETCH = 'SEARCH_LIST_FETCH'; -export const SEARCH_LIST_RESET = 'SEARCH_LIST_RESET'; +export const SEARCHLIST_FETCH = 'SEARCHLIST_FETCH'; +export const SEARCHLIST_RESET = 'SEARCHLIST_RESET'; -const SEARCH_LIST_FETCH_REQUEST = 'SEARCH_LIST_FETCH_REQUEST'; -const SEARCH_LIST_FETCH_SUCCESS = 'SEARCH_LIST_FETCH_SUCCESS'; -const SEARCH_LIST_FETCH_FAILURE = 'SEARCH_LIST_FETCH_FAILURE'; +const SEARCHLIST_FETCH_SUCCESS = 'SEARCHLIST_FETCH_SUCCESS'; +const SEARCHLIST_FETCH_FAILURE = 'SEARCHLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchSearchList = createAction(SEARCH_LIST_FETCH); -export const resetSearchList = createAction(SEARCH_LIST_RESET); +export const fetchSearchList = createAction(SEARCHLIST_FETCH); +export const resetSearchList = createAction(SEARCHLIST_RESET); -export const request = createAction(SEARCH_LIST_FETCH_REQUEST); -export const success = createAction(SEARCH_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(SEARCH_LIST_FETCH_FAILURE); +export const fetchSearchListSuccess = createAction(SEARCHLIST_FETCH_SUCCESS); +export const fetchSearchListFailure = createAction(SEARCHLIST_FETCH_FAILURE); // ********************************* // Reducer @@ -37,13 +35,13 @@ const defaultSearchListState = { }; export default handleActions({ - [SEARCH_LIST_FETCH_REQUEST]: (state, action) => ({ + [SEARCHLIST_FETCH]: (state, action) => ({ ...state, isRefreshing: !action.payload.isEndReached, isEndReached: action.payload.isEndReached, didInvalidate: false }), - [SEARCH_LIST_FETCH_SUCCESS]: (state, action) => { + [SEARCHLIST_FETCH_SUCCESS]: (state, action) => { let { payload: topicList } = action; @@ -65,11 +63,11 @@ export default handleActions({ errCode: topicList.errcode }; }, - [SEARCH_LIST_FETCH_FAILURE]: (state, action) => ({ + [SEARCHLIST_FETCH_FAILURE]: (state, action) => ({ ...state, isRefreshing: false, isEndReached: false, didInvalidate: false }), - [SEARCH_LIST_RESET]: () => defaultSearchListState + [SEARCHLIST_RESET]: () => defaultSearchListState }, defaultSearchListState); diff --git a/src/modules/topic/searchList/searchList.epics.js b/src/modules/topic/searchList/searchList.epics.js new file mode 100644 index 0000000..8692a8c --- /dev/null +++ b/src/modules/topic/searchList/searchList.epics.js @@ -0,0 +1,28 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { mergeMap, map } from 'rxjs/operators'; +import { + SEARCHLIST_FETCH, + fetchSearchListSuccess, + fetchSearchListFailure +} from './searchList.ducks'; +import api from '~/services/api'; + +const fetchSearchList = (action$) => action$.pipe( + ofType(SEARCHLIST_FETCH), + mergeMap(action => api.fetchSearchList(action.payload) + .then(({ + data, + error + }) => { + if (!error) { + return fetchSearchListSuccess(data); + } else { + return fetchSearchListFailure(error); + } + }) + ) +); + +export default combineEpics( + fetchSearchList +); diff --git a/src/modules/topic/topicList/topicList.ducks.js b/src/modules/topic/topicList/topicList.ducks.js index 526760a..e47dcc3 100644 --- a/src/modules/topic/topicList/topicList.ducks.js +++ b/src/modules/topic/topicList/topicList.ducks.js @@ -6,23 +6,23 @@ import _ from 'lodash'; // Actions // ********************************* -export const TOPIC_LIST_FETCH = 'TOPIC_LIST_FETCH'; -export const TOPIC_LIST_INVALIDATE = 'TOPIC_LIST_INVALIDATE'; -export const TOPIC_LIST_RESET = 'TOPIC_LIST_RESET'; +export const TOPICLIST_FETCH = 'TOPICLIST_FETCH'; +export const TOPICLIST_INVALIDATE = 'TOPICLIST_INVALIDATE'; +export const TOPICLIST_RESET = 'TOPICLIST_RESET'; -const TOPIC_LIST_FETCH_SUCCESS = 'TOPIC_LIST_FETCH_SUCCESS'; -const TOPIC_LIST_FETCH_FAILURE = 'TOPIC_LIST_FETCH_FAILURE'; +const TOPICLIST_FETCH_SUCCESS = 'TOPICLIST_FETCH_SUCCESS'; +const TOPICLIST_FETCH_FAILURE = 'TOPICLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchTopicList = createAction(TOPIC_LIST_FETCH); -export const invalidateTopicList = createAction(TOPIC_LIST_INVALIDATE); -export const resetTopicList = createAction(TOPIC_LIST_RESET); +export const fetchTopicList = createAction(TOPICLIST_FETCH); +export const invalidateTopicList = createAction(TOPICLIST_INVALIDATE); +export const resetTopicList = createAction(TOPICLIST_RESET); -export const fetchTopicListSuccess = createAction(TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const fetchTopicListFailure = createAction(TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); +export const fetchTopicListSuccess = createAction(TOPICLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchTopicListFailure = createAction(TOPICLIST_FETCH_FAILURE, null, (...args) => args[1]); // ********************************* // Reducer @@ -43,7 +43,7 @@ const defaultTopicListState = { }; export default handleActions({ - [TOPIC_LIST_INVALIDATE]: (state, action) => { + [TOPICLIST_INVALIDATE]: (state, action) => { let { boardId, sortType } = action.payload; return { ...state, @@ -56,7 +56,7 @@ export default handleActions({ } }; }, - [TOPIC_LIST_FETCH]: (state, action) => { + [TOPICLIST_FETCH]: (state, action) => { let { boardId, sortType, isEndReached } = action.payload; return { ...state, @@ -71,7 +71,7 @@ export default handleActions({ } }; }, - [TOPIC_LIST_FETCH_SUCCESS]: (state, action) => { + [TOPICLIST_FETCH_SUCCESS]: (state, action) => { let { payload: topicList, meta: { @@ -99,7 +99,7 @@ export default handleActions({ } }; }, - [TOPIC_LIST_FETCH_FAILURE]: (state, action) => { + [TOPICLIST_FETCH_FAILURE]: (state, action) => { let { boardId, sortType } = action.meta; return { ...state, @@ -115,7 +115,7 @@ export default handleActions({ }; }, // In case there is forum or sub forum we have no access. - [TOPIC_LIST_RESET]: (state, action) => { + [TOPICLIST_RESET]: (state, action) => { let { boardId, sortType } = action.payload; return { ...state, diff --git a/src/modules/topic/topicList/topicList.epics.js b/src/modules/topic/topicList/topicList.epics.js index c51e4d0..0bea809 100644 --- a/src/modules/topic/topicList/topicList.epics.js +++ b/src/modules/topic/topicList/topicList.epics.js @@ -1,29 +1,27 @@ import { combineEpics, ofType } from 'redux-observable'; import { mergeMap, map } from 'rxjs/operators'; import { - TOPIC_LIST_FETCH, + TOPICLIST_FETCH, fetchTopicListSuccess, fetchTopicListFailure } from './topicList.ducks'; import api from '~/services/api'; -const fetchTopicList = (action$) => { - return action$.pipe( - ofType(TOPIC_LIST_FETCH), - mergeMap(action => api.fetchTopicList(action.payload) - .then(({ - data, - error - }) => { - if (!error) { - return fetchTopicListSuccess(data, action.payload); - } else { - return fetchTopicListFailure(error, action.payload); - } - }) - ) - ); -}; +const fetchTopicList = (action$) => action$.pipe( + ofType(TOPICLIST_FETCH), + mergeMap(action => api.fetchTopicList(action.payload) + .then(({ + data, + error + }) => { + if (!error) { + return fetchTopicListSuccess(data, action.payload); + } else { + return fetchTopicListFailure(error, action.payload); + } + }) + ) +); export default combineEpics( fetchTopicList diff --git a/src/sagas/index.js b/src/sagas/index.js index 6b321ec..ee01c15 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -5,7 +5,6 @@ import * as sessionActions from '~/modules/user/session.ducks'; import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; import * as forumListActions from '~/modules/forum/forumList.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; -import * as searchListActions from '~/modules/topic/searchList.ducks'; import * as topicActions from '~/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; @@ -22,7 +21,6 @@ const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLogi const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchForumListApi = fetchResource.bind(null, forumListActions, api.fetchForumList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); -const fetchSearchListApi = fetchResource.bind(null, searchListActions, api.fetchSearchList); const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); @@ -147,15 +145,6 @@ function* fetchNotifyList(payload) { // } } -// search list sagas - -function* watchSearchList() { - while(true) { - const { payload } = yield take(searchListActions.SEARCH_LIST_FETCH); - yield fork(fetchSearchListApi, payload); - } -} - // topic sagas function* watchTopic() { @@ -234,7 +223,6 @@ export default function* rootSaga() { yield fork(watchUserTopicList); yield fork(watchForumList); yield fork(watchNotifyList); - yield fork(watchSearchList); yield fork(watchTopic); yield fork(watchPmSessionList); yield fork(watchPmList); From a0b535fe9a7a55f5d089fe1c5b33d68959f48ec8 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 26 Aug 2018 17:49:09 +0800 Subject: [PATCH 20/58] fix: cancel previous search to avoid next search to be overwrited --- src/containers/Search/Search.js | 8 +++++++- src/modules/topic/searchList/searchList.ducks.js | 2 ++ src/modules/topic/searchList/searchList.epics.js | 15 ++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 9a0cf7b..638e805 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -9,7 +9,11 @@ import SearchBar from 'react-native-search-bar'; import TopicList from '~/components/TopicList/TopicList'; import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import MENUS from '~/constants/menus'; -import { fetchSearchList, resetSearchList } from '~/modules/topic/searchList/searchList.ducks'; +import { + fetchSearchList, + cancelSearchList, + resetSearchList +} from '~/modules/topic/searchList/searchList.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; @@ -33,6 +37,7 @@ class Search extends Component { } componentWillUnmount() { + this.props.cancelSearchList(); this.props.resetSearchList(); } @@ -117,5 +122,6 @@ function mapStateToProps({ searchList, session }) { export default connect(mapStateToProps, { fetchSearchList, + cancelSearchList, resetSearchList })(Search); diff --git a/src/modules/topic/searchList/searchList.ducks.js b/src/modules/topic/searchList/searchList.ducks.js index 7724498..624eca5 100644 --- a/src/modules/topic/searchList/searchList.ducks.js +++ b/src/modules/topic/searchList/searchList.ducks.js @@ -5,6 +5,7 @@ import { createAction, handleActions } from 'redux-actions'; // ********************************* export const SEARCHLIST_FETCH = 'SEARCHLIST_FETCH'; +export const SEARCHLIST_CANCEL = 'SEARCHLIST_CANCEL'; export const SEARCHLIST_RESET = 'SEARCHLIST_RESET'; const SEARCHLIST_FETCH_SUCCESS = 'SEARCHLIST_FETCH_SUCCESS'; @@ -15,6 +16,7 @@ const SEARCHLIST_FETCH_FAILURE = 'SEARCHLIST_FETCH_FAILURE'; // ********************************* export const fetchSearchList = createAction(SEARCHLIST_FETCH); +export const cancelSearchList = createAction(SEARCHLIST_CANCEL); export const resetSearchList = createAction(SEARCHLIST_RESET); export const fetchSearchListSuccess = createAction(SEARCHLIST_FETCH_SUCCESS); diff --git a/src/modules/topic/searchList/searchList.epics.js b/src/modules/topic/searchList/searchList.epics.js index 8692a8c..dd177a6 100644 --- a/src/modules/topic/searchList/searchList.epics.js +++ b/src/modules/topic/searchList/searchList.epics.js @@ -1,7 +1,9 @@ import { combineEpics, ofType } from 'redux-observable'; -import { mergeMap, map } from 'rxjs/operators'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map, takeUntil } from 'rxjs/operators'; import { SEARCHLIST_FETCH, + SEARCHLIST_CANCEL, fetchSearchListSuccess, fetchSearchListFailure } from './searchList.ducks'; @@ -9,8 +11,8 @@ import api from '~/services/api'; const fetchSearchList = (action$) => action$.pipe( ofType(SEARCHLIST_FETCH), - mergeMap(action => api.fetchSearchList(action.payload) - .then(({ + mergeMap(action => fromPromise(api.fetchSearchList(action.payload)).pipe( + map(({ data, error }) => { @@ -19,8 +21,11 @@ const fetchSearchList = (action$) => action$.pipe( } else { return fetchSearchListFailure(error); } - }) - ) + }), + takeUntil(action$.pipe( + ofType(SEARCHLIST_CANCEL) + )) + )) ); export default combineEpics( From b2a7fc72dfc44ffe89ca44653901ab66d6fefa5e Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 00:40:08 +0800 Subject: [PATCH 21/58] refactor: replace redux-saga with redux-observable for forum list --- .../ForumListModal/ForumListModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 2 +- src/containers/ForumList/ForumList.js | 2 +- .../forum/{ => forumList}/forumList.ducks.js | 26 ++++++++--------- .../forum/forumList/forumList.epics.js | 29 +++++++++++++++++++ src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- src/sagas/index.js | 20 ------------- 8 files changed, 47 insertions(+), 38 deletions(-) rename src/modules/forum/{ => forumList}/forumList.ducks.js (63%) create mode 100644 src/modules/forum/forumList/forumList.epics.js diff --git a/src/components/ForumListModal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js index b595246..fa5d0b6 100644 --- a/src/components/ForumListModal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import Header from '~/components/Header/Header'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 217e2e1..89c5439 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -12,7 +12,7 @@ import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList/topicList.ducks'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index f129aa8..8535bad 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -8,7 +8,7 @@ import { import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import MENUS from '~/constants/menus'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/modules/forum/forumList.ducks.js b/src/modules/forum/forumList/forumList.ducks.js similarity index 63% rename from src/modules/forum/forumList.ducks.js rename to src/modules/forum/forumList/forumList.ducks.js index 7c3d50d..d12f1e4 100644 --- a/src/modules/forum/forumList.ducks.js +++ b/src/modules/forum/forumList/forumList.ducks.js @@ -6,23 +6,21 @@ import _ from 'lodash'; // Actions // ********************************* -export const FORUM_LIST_FETCH = 'FORUM_LIST_FETCH'; -export const FORUM_LIST_INVALIDATE = 'FORUM_LIST_INVALIDATE'; +export const FORUMLIST_FETCH = 'FORUMLIST_FETCH'; +export const FORUMLIST_INVALIDATE = 'FORUMLIST_INVALIDATE'; -const FORUM_LIST_FETCH_REQUEST = 'FORUM_LIST_FETCH_REQUEST'; -const FORUM_LIST_FETCH_SUCCESS = 'FORUM_LIST_FETCH_SUCCESS'; -const FORUM_LIST_FETCH_FAILURE = 'FORUM_LIST_FETCH_FAILURE'; +const FORUMLIST_FETCH_SUCCESS = 'FORUMLIST_FETCH_SUCCESS'; +const FORUMLIST_FETCH_FAILURE = 'FORUMLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchForumList = createAction(FORUM_LIST_FETCH); -export const invalidateForumList = createAction(FORUM_LIST_INVALIDATE); +export const fetchForumList = createAction(FORUMLIST_FETCH); +export const invalidateForumList = createAction(FORUMLIST_INVALIDATE); -export const request = createAction(FORUM_LIST_FETCH_REQUEST); -export const success = createAction(FORUM_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(FORUM_LIST_FETCH_FAILURE, null, (...args) => args[1]); +export const fetchForumListSuccess = createAction(FORUMLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchForumListFailure = createAction(FORUMLIST_FETCH_FAILURE, null, (...args) => args[1]); // ********************************* // Reducer @@ -36,7 +34,7 @@ const defaultForumListState = { }; export default handleActions({ - [FORUM_LIST_INVALIDATE]: (state, action) => { + [FORUMLIST_INVALIDATE]: (state, action) => { let { boardId } = action.payload; return { ...state, @@ -46,7 +44,7 @@ export default handleActions({ } }; }, - [FORUM_LIST_FETCH_REQUEST]: (state, action) => { + [FORUMLIST_FETCH]: (state, action) => { let { boardId } = action.payload; return { ...state, @@ -57,7 +55,7 @@ export default handleActions({ } }; }, - [FORUM_LIST_FETCH_SUCCESS]: (state, action) => { + [FORUMLIST_FETCH_SUCCESS]: (state, action) => { let { payload: forumList, meta: { @@ -74,7 +72,7 @@ export default handleActions({ } }; }, - [FORUM_LIST_FETCH_FAILURE]: (state, action) => { + [FORUMLIST_FETCH_FAILURE]: (state, action) => { let { boardId } = action.meta; return { ...state, diff --git a/src/modules/forum/forumList/forumList.epics.js b/src/modules/forum/forumList/forumList.epics.js new file mode 100644 index 0000000..96b431a --- /dev/null +++ b/src/modules/forum/forumList/forumList.epics.js @@ -0,0 +1,29 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + FORUMLIST_FETCH, + fetchForumListSuccess, + fetchForumListFailure +} from './forumList.ducks'; +import api from '~/services/api'; + +const fetchForumList = (action$) => action$.pipe( + ofType(FORUMLIST_FETCH), + mergeMap(action => fromPromise(api.fetchForumList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchForumListSuccess(data, action.payload); + } else { + return fetchForumListFailure(error, action.payload); + } + }) + )) +); + +export default combineEpics( + fetchForumList +); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 69355c2..5624fcd 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -1,8 +1,10 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; +import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; export default combineEpics( topicList, + forumList, searchList ); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index b4af231..525f263 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -1,7 +1,7 @@ import { combineReducers } from 'redux'; import session from '~/modules/user/session.ducks'; import topicList from '~/modules/topic/topicList/topicList.ducks'; -import forumList from '~/modules/forum/forumList.ducks'; +import forumList from '~/modules/forum/forumList/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList.ducks'; diff --git a/src/sagas/index.js b/src/sagas/index.js index ee01c15..7b45dfc 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -3,7 +3,6 @@ import { take, fork, select, put, call } from 'redux-saga/effects'; import * as sessionActions from '~/modules/user/session.ducks'; import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; -import * as forumListActions from '~/modules/forum/forumList.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; import * as topicActions from '~/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; @@ -19,7 +18,6 @@ import api from '~/services/api'; const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); -const fetchForumListApi = fetchResource.bind(null, forumListActions, api.fetchForumList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); @@ -109,23 +107,6 @@ function* fetchUserTopicList(payload) { } } -// forum list sagas - -function* watchForumList() { - while(true) { - const { payload } = yield take(forumListActions.FORUM_LIST_FETCH); - yield fork(fetchForumList, payload); - } -} - -function* fetchForumList(payload) { - const state = yield select(); - - if (cacheManager.shouldFetchList(state, 'forumList', payload.boardId)) { - yield fork(fetchForumListApi, payload); - } -} - // notify list sagas function* watchNotifyList() { @@ -221,7 +202,6 @@ export default function* rootSaga() { yield fork(watchRetrieveSession); yield fork(watchLogin); yield fork(watchUserTopicList); - yield fork(watchForumList); yield fork(watchNotifyList); yield fork(watchTopic); yield fork(watchPmSessionList); From 8b8cc237e6341bb99db0c774dfa774480dd8e720 Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 00:46:42 +0800 Subject: [PATCH 22/58] fix: missing cache check --- .../forum/forumList/forumList.ducks.js | 4 +- .../forum/forumList/forumList.epics.js | 38 +++++++++++-------- .../topic/topicList/topicList.ducks.js | 4 +- .../topic/topicList/topicList.epics.js | 38 ++++++++++++------- 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/modules/forum/forumList/forumList.ducks.js b/src/modules/forum/forumList/forumList.ducks.js index d12f1e4..95bc354 100644 --- a/src/modules/forum/forumList/forumList.ducks.js +++ b/src/modules/forum/forumList/forumList.ducks.js @@ -9,6 +9,7 @@ import _ from 'lodash'; export const FORUMLIST_FETCH = 'FORUMLIST_FETCH'; export const FORUMLIST_INVALIDATE = 'FORUMLIST_INVALIDATE'; +const FORUMLIST_FETCH_REQUEST = 'FORUMLIST_FETCH_REQUEST'; const FORUMLIST_FETCH_SUCCESS = 'FORUMLIST_FETCH_SUCCESS'; const FORUMLIST_FETCH_FAILURE = 'FORUMLIST_FETCH_FAILURE'; @@ -19,6 +20,7 @@ const FORUMLIST_FETCH_FAILURE = 'FORUMLIST_FETCH_FAILURE'; export const fetchForumList = createAction(FORUMLIST_FETCH); export const invalidateForumList = createAction(FORUMLIST_INVALIDATE); +export const fetchForumListRequest = createAction(FORUMLIST_FETCH_REQUEST); export const fetchForumListSuccess = createAction(FORUMLIST_FETCH_SUCCESS, null, (...args) => args[1]); export const fetchForumListFailure = createAction(FORUMLIST_FETCH_FAILURE, null, (...args) => args[1]); @@ -44,7 +46,7 @@ export default handleActions({ } }; }, - [FORUMLIST_FETCH]: (state, action) => { + [FORUMLIST_FETCH_REQUEST]: (state, action) => { let { boardId } = action.payload; return { ...state, diff --git a/src/modules/forum/forumList/forumList.epics.js b/src/modules/forum/forumList/forumList.epics.js index 96b431a..0df66c8 100644 --- a/src/modules/forum/forumList/forumList.epics.js +++ b/src/modules/forum/forumList/forumList.epics.js @@ -1,27 +1,35 @@ import { combineEpics, ofType } from 'redux-observable'; -import { from as fromPromise } from 'rxjs'; -import { mergeMap, map } from 'rxjs/operators'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map, filter } from 'rxjs/operators'; import { FORUMLIST_FETCH, + fetchForumListRequest, fetchForumListSuccess, fetchForumListFailure } from './forumList.ducks'; import api from '~/services/api'; +import cacheManager from '~/services/cacheManager'; -const fetchForumList = (action$) => action$.pipe( +const fetchForumList = (action$, state$) => action$.pipe( ofType(FORUMLIST_FETCH), - mergeMap(action => fromPromise(api.fetchForumList(action.payload)).pipe( - map(({ - data, - error - }) => { - if (!error) { - return fetchForumListSuccess(data, action.payload); - } else { - return fetchForumListFailure(error, action.payload); - } - }) - )) + filter(action => cacheManager.shouldFetchList(state$.value, 'forumList', action.payload.boardId)), + mergeMap(action => + concat( + of(fetchForumListRequest(action.payload)), + fromPromise(api.fetchForumList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchForumListSuccess(data, action.payload); + } else { + return fetchForumListFailure(error, action.payload); + } + }) + ) + ) + ) ); export default combineEpics( diff --git a/src/modules/topic/topicList/topicList.ducks.js b/src/modules/topic/topicList/topicList.ducks.js index e47dcc3..ac79228 100644 --- a/src/modules/topic/topicList/topicList.ducks.js +++ b/src/modules/topic/topicList/topicList.ducks.js @@ -10,6 +10,7 @@ export const TOPICLIST_FETCH = 'TOPICLIST_FETCH'; export const TOPICLIST_INVALIDATE = 'TOPICLIST_INVALIDATE'; export const TOPICLIST_RESET = 'TOPICLIST_RESET'; +const TOPICLIST_FETCH_REQUEST = 'TOPICLIST_FETCH_REQUEST'; const TOPICLIST_FETCH_SUCCESS = 'TOPICLIST_FETCH_SUCCESS'; const TOPICLIST_FETCH_FAILURE = 'TOPICLIST_FETCH_FAILURE'; @@ -21,6 +22,7 @@ export const fetchTopicList = createAction(TOPICLIST_FETCH); export const invalidateTopicList = createAction(TOPICLIST_INVALIDATE); export const resetTopicList = createAction(TOPICLIST_RESET); +export const fetchTopicListRequest = createAction(TOPICLIST_FETCH_REQUEST); export const fetchTopicListSuccess = createAction(TOPICLIST_FETCH_SUCCESS, null, (...args) => args[1]); export const fetchTopicListFailure = createAction(TOPICLIST_FETCH_FAILURE, null, (...args) => args[1]); @@ -56,7 +58,7 @@ export default handleActions({ } }; }, - [TOPICLIST_FETCH]: (state, action) => { + [TOPICLIST_FETCH_REQUEST]: (state, action) => { let { boardId, sortType, isEndReached } = action.payload; return { ...state, diff --git a/src/modules/topic/topicList/topicList.epics.js b/src/modules/topic/topicList/topicList.epics.js index 0bea809..67a7bcb 100644 --- a/src/modules/topic/topicList/topicList.epics.js +++ b/src/modules/topic/topicList/topicList.epics.js @@ -1,25 +1,37 @@ import { combineEpics, ofType } from 'redux-observable'; -import { mergeMap, map } from 'rxjs/operators'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map, filter } from 'rxjs/operators'; import { TOPICLIST_FETCH, + fetchTopicListRequest, fetchTopicListSuccess, fetchTopicListFailure } from './topicList.ducks'; import api from '~/services/api'; +import cacheManager from '~/services/cacheManager'; -const fetchTopicList = (action$) => action$.pipe( +const fetchTopicList = (action$, state$) => action$.pipe( ofType(TOPICLIST_FETCH), - mergeMap(action => api.fetchTopicList(action.payload) - .then(({ - data, - error - }) => { - if (!error) { - return fetchTopicListSuccess(data, action.payload); - } else { - return fetchTopicListFailure(error, action.payload); - } - }) + filter(action => { + const { boardId, sortType } = action.payload; + return cacheManager.shouldFetchList(state$.value, 'topicList', boardId, sortType); + }), + mergeMap(action => + concat( + of(fetchTopicListRequest(action.payload)), + fromPromise(api.fetchTopicList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchTopicListSuccess(data, action.payload); + } else { + return fetchTopicListFailure(error, action.payload); + } + }) + ) + ) ) ); From eff5b952538982d7370b166e595c1ae71a2b597d Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 13:09:23 +0800 Subject: [PATCH 23/58] refactor: replace redux-saga with redux-observable for settings --- src/containers/Settings/Settings.js | 3 +- src/modules/root/rootEpic.js | 4 ++- src/modules/settings/settings.epics.js | 41 ++++++++++++++++++++++++++ src/sagas/index.js | 39 ------------------------ 4 files changed, 45 insertions(+), 42 deletions(-) create mode 100644 src/modules/settings/settings.epics.js diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 8d594a6..2788710 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -13,7 +13,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; -import { retrieveSettingsFromStorage, storeSettingsToStorage } from '~/modules/settings/settings.ducks'; +import { storeSettingsToStorage } from '~/modules/settings/settings.ducks'; import { resetAlert } from '~/modules/message/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; @@ -89,7 +89,6 @@ function mapStateToProps({ settings }) { } export default connect(mapStateToProps, { - retrieveSettingsFromStorage, storeSettingsToStorage, resetAlert })(Settings); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 5624fcd..032743d 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -2,9 +2,11 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import settings from '~/modules/settings/settings.epics'; export default combineEpics( topicList, forumList, - searchList + searchList, + settings ); diff --git a/src/modules/settings/settings.epics.js b/src/modules/settings/settings.epics.js new file mode 100644 index 0000000..007b7c5 --- /dev/null +++ b/src/modules/settings/settings.epics.js @@ -0,0 +1,41 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { AsyncStorage } from 'react-native'; +import { + SETTINGS_RETRIEVE, + SETTINGS_STORE, + storeSettingsToRedux +} from './settings.ducks'; +import api from '~/services/api'; + +const retrieveSettings = (action$) => action$.pipe( + ofType(SETTINGS_RETRIEVE), + mergeMap(action => fromPromise(AsyncStorage.getItem('settings')).pipe( + map(settings => { + if (settings) { + settings = JSON.parse(settings); + return storeSettingsToRedux(settings); + } + }) + )) +); + +const storeSettings = (action$) => action$.pipe( + ofType(SETTINGS_STORE), + mergeMap(action => fromPromise(AsyncStorage.getItem('settings')).pipe( + map(settings => { + // Get new settings. + let newSettings = Object.assign({}, JSON.parse(settings), action.payload); + // Store new settings in storage. + AsyncStorage.setItem('settings', JSON.stringify(newSettings)); + // Update redux store. + return storeSettingsToRedux(newSettings); + }) + )) +); + +export default combineEpics( + retrieveSettings, + storeSettings +); diff --git a/src/sagas/index.js b/src/sagas/index.js index 7b45dfc..2fc4951 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -8,7 +8,6 @@ import * as topicActions from '~/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; -import * as settingsActions from '~/modules/settings/settings.ducks'; import * as userActions from '~/modules/user/user.ducks'; import * as friendListActions from '~/modules/user/friendList.ducks'; @@ -53,42 +52,6 @@ function* watchLogin() { } } -// settings sagas - -function* watchRetrieveSettings() { - while(true) { - yield take(settingsActions.SETTINGS_RETRIEVE); - let settings = yield call(retrieveSettingsFromStorage); - - if (settings) { - settings = JSON.parse(settings); - yield put(settingsActions.storeSettingsToRedux(settings)); - } - } -} - -function retrieveSettingsFromStorage() { - return new Promise(resolve => AsyncStorage.getItem('settings').then(resolve)); -} - -function* watchStoreSettings() { - while(true) { - const { payload } = yield take(settingsActions.SETTINGS_STORE); - // get old settings - let settings = yield call(retrieveSettingsFromStorage); - // merge with new settings - let newSettings = Object.assign({}, JSON.parse(settings), payload); - // store new settings in storage - yield call(storeSettingsToStorage, JSON.stringify(newSettings)); - // update redux store - yield put(settingsActions.storeSettingsToRedux(newSettings)); - } -} - -function storeSettingsToStorage(settings) { - return new Promise(resolve => AsyncStorage.setItem('settings', settings).then(resolve)); -} - // user topic list sags function* watchUserTopicList() { @@ -207,8 +170,6 @@ export default function* rootSaga() { yield fork(watchPmSessionList); yield fork(watchPmList); yield fork(watchAlerts); - yield fork(watchRetrieveSettings); - yield fork(watchStoreSettings); yield fork(watchUsers); yield fork(watchFriendList); } From c68ff5fb0d4b89fbaf8592b6395ae3b6668405da Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 13:25:04 +0800 Subject: [PATCH 24/58] refactor: replace redux-saga with redux-observable for topic --- src/components/ReplyModal/ReplyModal.js | 2 +- src/containers/TopicDetail/TopicDetail.js | 2 +- src/modules/root/rootEpic.js | 4 +++ src/modules/root/rootReducer.js | 2 +- src/modules/topic/{ => topic}/topic.ducks.js | 8 ++---- src/modules/topic/topic/topic.epics.js | 29 ++++++++++++++++++++ src/sagas/index.js | 12 -------- 7 files changed, 39 insertions(+), 20 deletions(-) rename src/modules/topic/{ => topic}/topic.ducks.js (92%) create mode 100644 src/modules/topic/topic/topic.epics.js diff --git a/src/components/ReplyModal/ReplyModal.js b/src/components/ReplyModal/ReplyModal.js index 334e7aa..bc10e7d 100644 --- a/src/components/ReplyModal/ReplyModal.js +++ b/src/components/ReplyModal/ReplyModal.js @@ -19,7 +19,7 @@ import ImageUploader from '~/components/ImageUploader/ImageUploader'; import MessageBar from '~/services/MessageBar'; import api from '~/services/api'; import { CUSTOM_EMOJIS } from '~/constants/emojis'; -import { fetchTopic } from '~/modules/topic/topic.ducks'; +import { fetchTopic } from '~/modules/topic/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index edeb5d9..8027c01 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -27,7 +27,7 @@ import SafariView from '~/services/SafariView'; import api from '~/services/api'; import { TOPIC_URL_ROOT } from '~/config'; import { parseContentWithEmoji } from '~/utils/contentParser'; -import { fetchTopic, resetTopic } from '~/modules/topic/topic.ducks'; +import { fetchTopic, resetTopic } from '~/modules/topic/topic/topic.ducks'; import mainStyles from '~/common/styles/Main.style'; import headerRightButtonStyles from '~/common/styles/HeaderRightButton.style'; diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 032743d..69b1f91 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -2,11 +2,15 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import topicItem from '~/modules/topic/topic/topic.epics'; import settings from '~/modules/settings/settings.epics'; export default combineEpics( topicList, forumList, searchList, + + topicItem, + settings ); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 525f263..665f24d 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -8,7 +8,7 @@ import pmSessionList from '~/modules/message/pmSessionList.ducks'; import pmList from '~/modules/message/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList.ducks'; import friendList from '~/modules/user/friendList.ducks'; -import topicItem from '~/modules/topic/topic.ducks'; +import topicItem from '~/modules/topic/topic/topic.ducks'; import userItem from '~/modules/user/user.ducks'; import alert from '~/modules/message/alert.ducks'; import settings from '~/modules/settings/settings.ducks'; diff --git a/src/modules/topic/topic.ducks.js b/src/modules/topic/topic/topic.ducks.js similarity index 92% rename from src/modules/topic/topic.ducks.js rename to src/modules/topic/topic/topic.ducks.js index 661af4b..368c728 100644 --- a/src/modules/topic/topic.ducks.js +++ b/src/modules/topic/topic/topic.ducks.js @@ -8,7 +8,6 @@ import _ from 'lodash'; export const TOPIC_FETCH = 'TOPIC_FETCH'; export const TOPIC_RESET = 'TOPIC_RESET'; -const TOPIC_FETCH_REQUEST = 'TOPIC_FETCH_REQUEST'; const TOPIC_FETCH_SUCCESS = 'TOPIC_FETCH_SUCCESS'; const TOPIC_FETCH_FAILURE = 'TOPIC_FETCH_FAILURE'; @@ -19,9 +18,8 @@ const TOPIC_FETCH_FAILURE = 'TOPIC_FETCH_FAILURE'; export const fetchTopic = createAction(TOPIC_FETCH); export const resetTopic = createAction(TOPIC_RESET); -export const request = createAction(TOPIC_FETCH_REQUEST); -export const success = createAction(TOPIC_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(TOPIC_FETCH_FAILURE); +export const fetchTopicSuccess = createAction(TOPIC_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchTopicFailure = createAction(TOPIC_FETCH_FAILURE); // ********************************* // Reducer @@ -58,7 +56,7 @@ const defaultTopicState = { }; export default handleActions({ - [TOPIC_FETCH_REQUEST]: (state, action) => { + [TOPIC_FETCH]: (state, action) => { let { topicId, isEndReached } = action.payload; return { ...state, diff --git a/src/modules/topic/topic/topic.epics.js b/src/modules/topic/topic/topic.epics.js new file mode 100644 index 0000000..938b783 --- /dev/null +++ b/src/modules/topic/topic/topic.epics.js @@ -0,0 +1,29 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + TOPIC_FETCH, + fetchTopicSuccess, + fetchTopicFailure +} from './topic.ducks'; +import api from '~/services/api'; + +const fetchTopic = (action$) => action$.pipe( + ofType(TOPIC_FETCH), + mergeMap(action => fromPromise(api.fetchTopic(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchTopicSuccess(data, action.payload); + } else { + return fetchTopicFailure(error); + } + }) + )) +); + +export default combineEpics( + fetchTopic +); diff --git a/src/sagas/index.js b/src/sagas/index.js index 2fc4951..f8091c6 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -4,7 +4,6 @@ import { take, fork, select, put, call } from 'redux-saga/effects'; import * as sessionActions from '~/modules/user/session.ducks'; import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; -import * as topicActions from '~/modules/topic/topic.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; @@ -18,7 +17,6 @@ import api from '~/services/api'; const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); -const fetchTopicApi = fetchResource.bind(null, topicActions, api.fetchTopic); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); @@ -89,15 +87,6 @@ function* fetchNotifyList(payload) { // } } -// topic sagas - -function* watchTopic() { - while(true) { - const { payload } = yield take(topicActions.TOPIC_FETCH); - yield fork(fetchTopicApi, payload); - } -} - // pm session list sagas function* watchPmSessionList() { @@ -166,7 +155,6 @@ export default function* rootSaga() { yield fork(watchLogin); yield fork(watchUserTopicList); yield fork(watchNotifyList); - yield fork(watchTopic); yield fork(watchPmSessionList); yield fork(watchPmList); yield fork(watchAlerts); From 099494b3d2d8cb56bb5654573ee8ad18b0905406 Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 14:54:46 +0800 Subject: [PATCH 25/58] docs: add more comments for topic data structure --- src/containers/TopicDetail/TopicDetail.js | 4 ++ src/modules/topic/topic/topic.ducks.js | 65 +++++++++++++++++------ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 8027c01..74379d1 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -105,6 +105,10 @@ class TopicDetail extends Component { componentWillReceiveProps(nextProps) { let { topicItem } = nextProps; + // Seems like the code here won't be invoked since we + // display login modal instead when user clicks topic in + // home page without credentials. See comments in + // `topic.ducks` for more information. if (topicItem.errCode) { AlertIOS.alert('提示', topicItem.errCode); nextProps.resetTopic({ topicId: this.topicId }); diff --git a/src/modules/topic/topic/topic.ducks.js b/src/modules/topic/topic/topic.ducks.js index 368c728..fac07aa 100644 --- a/src/modules/topic/topic/topic.ducks.js +++ b/src/modules/topic/topic/topic.ducks.js @@ -25,28 +25,61 @@ export const fetchTopicFailure = createAction(TOPIC_FETCH_FAILURE); // Reducer // ********************************* -// We don't use `cacheManager` to check `shouldFetchTopicItem` in sagas -// since topic comments are back with topic details together, and we don't -// want to cache comments (that said we will always get latest comments with -// latest topic information in `componentDidMount` every time). +// ********************************* +// Why we need to use key-value for each topic in redux store? +// ********************************* +// +// First of all, if we use key-value, that means we want to cache each topic. +// However, the comments of a topic will back with topic information together, +// that means we may won't get latest comments in next time. +// +// In this way, sounds like key-value is not needed, just use object to store +// one specific topic is enough. +// +// In this app, we have one scenario, we can navigate from topic A to topic B +// with inside link. In this case, if we touch back button to topic A, we will +// still see the content of topic B. That's the reason. + +// ********************************* +// If we don't cache each topic content, why we don't reset/clear the topic +// content in `componentWillUnmount`? +// ********************************* // -// In this way, we should not also reset/clear the topic item in `componentWillUnmount`. -// Say we navigate from topic A --> topic B --> topic A, then touch back twice to topic -// A. We will get blank page since the content of topic A has been `reset` in the third +// 1. We have no need to reset/clear to content since we don't use `cacheManager` +// to check whether we can fetch the topic, that said we will always get latest +// topic content in `componentDidMount` to overwrite the old one. +// +// 2. If we nagivate from topic A --> topic B --> topic A, or topic A --> topic A +// (try it out in http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1705815), +// when we touch back button to first topic A page, we will see nothing, +// since the content of topic A has been `reset/clear` in the last topic A // page's `componentWillUnmount`. + +// ********************************* +// Any disadvantages if we don's reset/clear the topic content? +// ********************************* // // The only disadvantage of not resetting topic item is that, if we navigate from -// topic A --> topic A (try it out in http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1705815), -// we will see the content of first topic A will replace with loading spinner since we trigger -// request action for topic A again. As tradeoff, I think it's not big deal. +// topic A --> topic A, we will see the content of first topic A will be replaced +// with loading spinner before the page transition since we trigger request action +// for topic A again. As tradeoff, I think it's not big deal. -// There is no race condition if we isolate every topic item via topicId in redux store. +// ********************************* +// Is there race condition? +// ********************************* +// +// There is also no race condition if we use key-value for each topic in redux store. // https://github.com/just4fun/stuhome/issues/25 +// +// So we have no need to use `takeUntil` to cancel fetch request when we leave the page +// before response back. But we need to do it in search page becasue we won't send request +// when we access search page and it may display previous search result without cancelling. const defaultState = {}; const defaultTopicState = { isFetching: false, isEndReached: false, + // Topic information. topic: null, // Comment list. list: [], @@ -112,13 +145,13 @@ export default handleActions({ } }; }, - // We didn't cahce topic item like topic list, because comment list - // will be returned with topic info together, that means we will also - // cache topic comments as well. + // This will only be triggerd if we get any error for topic item. // - // This will be triggerd in `componentWillUnmount()`. + // Since the login modal will be displayed if the user clicks topic + // in home page without credentials instead of triggering this action, + // seems like it's useless now, but I'd like to leave it here. [TOPIC_RESET]: (state, action) => { let { topicId } = action.payload; return _.pickBy(state, (value, key) => +key !== +topicId); } -}, defaultTopicState); +}, defaultState); From 0a5480908989c70ab5a720711408a17af742424a Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 15:16:42 +0800 Subject: [PATCH 26/58] refactor: replace redux-saga with redux-observable for friend list --- .../FriendListModal/FriendListModal.js | 2 +- src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- .../user/{ => friendList}/friendList.ducks.js | 26 ++++++++--------- .../user/friendList/friendList.epics.js | 29 +++++++++++++++++++ src/sagas/index.js | 20 ------------- 6 files changed, 45 insertions(+), 36 deletions(-) rename src/modules/user/{ => friendList}/friendList.ducks.js (59%) create mode 100644 src/modules/user/friendList/friendList.epics.js diff --git a/src/components/FriendListModal/FriendListModal.js b/src/components/FriendListModal/FriendListModal.js index 3f9eaba..8a58d8e 100644 --- a/src/components/FriendListModal/FriendListModal.js +++ b/src/components/FriendListModal/FriendListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import FriendList from '~/components/FriendList/FriendList'; import Header from '~/components/Header/Header'; -import { invalidateFriendList, fetchFriendList } from '~/modules/user/friendList.ducks'; +import { invalidateFriendList, fetchFriendList } from '~/modules/user/friendList/friendList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 69b1f91..c7915eb 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -2,6 +2,7 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import friendList from '~/modules/user/friendList/friendList.epics'; import topicItem from '~/modules/topic/topic/topic.epics'; import settings from '~/modules/settings/settings.epics'; @@ -9,6 +10,7 @@ export default combineEpics( topicList, forumList, searchList, + friendList, topicItem, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 665f24d..a229cd5 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -7,7 +7,7 @@ import notifyList from '~/modules/message/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList.ducks'; import pmList from '~/modules/message/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList.ducks'; -import friendList from '~/modules/user/friendList.ducks'; +import friendList from '~/modules/user/friendList/friendList.ducks'; import topicItem from '~/modules/topic/topic/topic.ducks'; import userItem from '~/modules/user/user.ducks'; import alert from '~/modules/message/alert.ducks'; diff --git a/src/modules/user/friendList.ducks.js b/src/modules/user/friendList/friendList.ducks.js similarity index 59% rename from src/modules/user/friendList.ducks.js rename to src/modules/user/friendList/friendList.ducks.js index 1a42a57..a662414 100644 --- a/src/modules/user/friendList.ducks.js +++ b/src/modules/user/friendList/friendList.ducks.js @@ -4,23 +4,21 @@ import { createAction, handleActions } from 'redux-actions'; // Actions // ********************************* -export const FRIEND_LIST_FETCH = 'FRIEND_LIST_FETCH'; -export const FRIEND_LIST_INVALIDATE = 'FRIEND_LIST_INVALIDATE'; +export const FRIENDLIST_FETCH = 'FRIENDLIST_FETCH'; +export const FRIENDLIST_INVALIDATE = 'FRIENDLIST_INVALIDATE'; -const FRIEND_LIST_FETCH_REQUEST = 'FRIEND_LIST_FETCH_REQUEST'; -const FRIEND_LIST_FETCH_SUCCESS = 'FRIEND_LIST_FETCH_SUCCESS'; -const FRIEND_LIST_FETCH_FAILURE = 'FRIEND_LIST_FETCH_FAILURE'; +const FRIENDLIST_FETCH_SUCCESS = 'FRIENDLIST_FETCH_SUCCESS'; +const FRIENDLIST_FETCH_FAILURE = 'FRIENDLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchFriendList = createAction(FRIEND_LIST_FETCH); -export const invalidateFriendList = createAction(FRIEND_LIST_INVALIDATE); +export const fetchFriendList = createAction(FRIENDLIST_FETCH); +export const invalidateFriendList = createAction(FRIENDLIST_INVALIDATE); -export const request = createAction(FRIEND_LIST_FETCH_REQUEST); -export const success = createAction(FRIEND_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(FRIEND_LIST_FETCH_FAILURE); +export const fetchFriendListSuccess = createAction(FRIENDLIST_FETCH_SUCCESS); +export const fetchFriendListFailure = createAction(FRIENDLIST_FETCH_FAILURE); // ********************************* // Reducer @@ -37,11 +35,11 @@ const defaultFriendListState = { }; export default handleActions({ - [FRIEND_LIST_INVALIDATE]: (state, action) => ({ + [FRIENDLIST_INVALIDATE]: (state, action) => ({ ...state, didInvalidate: true }), - [FRIEND_LIST_FETCH_REQUEST]: (state, action) => { + [FRIENDLIST_FETCH]: (state, action) => { let { isEndReached } = action.payload; return { ...state, @@ -50,7 +48,7 @@ export default handleActions({ didInvalidate: false }; }, - [FRIEND_LIST_FETCH_SUCCESS]: (state, action) => { + [FRIENDLIST_FETCH_SUCCESS]: (state, action) => { let { payload: friendList } = action; @@ -70,7 +68,7 @@ export default handleActions({ errCode: friendList.errcode }; }, - [FRIEND_LIST_FETCH_FAILURE]: (state, action) => ({ + [FRIENDLIST_FETCH_FAILURE]: (state, action) => ({ ...state, isRefreshing: false, isEndReached: false, diff --git a/src/modules/user/friendList/friendList.epics.js b/src/modules/user/friendList/friendList.epics.js new file mode 100644 index 0000000..c8196f9 --- /dev/null +++ b/src/modules/user/friendList/friendList.epics.js @@ -0,0 +1,29 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + FRIENDLIST_FETCH, + fetchFriendListSuccess, + fetchFriendListFailure +} from './friendList.ducks'; +import api from '~/services/api'; + +const fetchFriendList = (action$) => action$.pipe( + ofType(FRIENDLIST_FETCH), + mergeMap(action => fromPromise(api.fetchFriendList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchFriendListSuccess(data); + } else { + return fetchFriendListFailure(error); + } + }) + )) +); + +export default combineEpics( + fetchFriendList +); diff --git a/src/sagas/index.js b/src/sagas/index.js index f8091c6..cd4ab91 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -8,7 +8,6 @@ import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; import * as userActions from '~/modules/user/user.ducks'; -import * as friendListActions from '~/modules/user/friendList.ducks'; import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; @@ -21,7 +20,6 @@ const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); const fetchUserApi = fetchResource.bind(null, userActions, api.fetchUser); -const fetchFriendListApi = fetchResource.bind(null, friendListActions, api.fetchFriendList); // user login sagas @@ -133,23 +131,6 @@ function* watchUsers() { } } -// friend list sagas - -function* watchFriendList() { - while(true) { - const { payload } = yield take(friendListActions.FRIEND_LIST_FETCH); - yield fork(fetchFriendList, payload); - } -} - -function* fetchFriendList(payload) { - const state = yield select(); - - if (cacheManager.shouldFetchList(state, 'friendList')) { - yield fork(fetchFriendListApi, payload); - } -} - export default function* rootSaga() { yield fork(watchRetrieveSession); yield fork(watchLogin); @@ -159,5 +140,4 @@ export default function* rootSaga() { yield fork(watchPmList); yield fork(watchAlerts); yield fork(watchUsers); - yield fork(watchFriendList); } From 7ea157bb489788978b74513a9014f2009e7da38a Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 20:17:23 +0800 Subject: [PATCH 27/58] refactor: replace redux-saga with redux-observable for user topic list --- src/containers/Individual/Individual.js | 2 +- src/modules/root/rootEpic.js | 2 + src/modules/root/rootReducer.js | 2 +- .../userTopicList.ducks.js | 28 ++++++------- .../user/userTopicList/userTopicList.epics.js | 40 +++++++++++++++++++ src/sagas/index.js | 21 ---------- 6 files changed, 58 insertions(+), 37 deletions(-) rename src/modules/user/{ => userTopicList}/userTopicList.ducks.js (72%) create mode 100644 src/modules/user/userTopicList/userTopicList.epics.js diff --git a/src/containers/Individual/Individual.js b/src/containers/Individual/Individual.js index 117893b..1aec651 100644 --- a/src/containers/Individual/Individual.js +++ b/src/containers/Individual/Individual.js @@ -12,7 +12,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import { HeaderBackButton } from 'react-navigation'; import TopicList from '~/components/TopicList/TopicList'; -import { invalidateUserTopicList, fetchUserTopicList } from '~/modules/user/userTopicList.ducks'; +import { invalidateUserTopicList, fetchUserTopicList } from '~/modules/user/userTopicList/userTopicList.ducks'; import { AVATAR_ROOT } from '~/config'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index c7915eb..b32274d 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -2,6 +2,7 @@ import { combineEpics } from 'redux-observable'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; import friendList from '~/modules/user/friendList/friendList.epics'; import topicItem from '~/modules/topic/topic/topic.epics'; import settings from '~/modules/settings/settings.epics'; @@ -10,6 +11,7 @@ export default combineEpics( topicList, forumList, searchList, + userTopicList, friendList, topicItem, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index a229cd5..0f1013e 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -6,7 +6,7 @@ import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList.ducks'; import pmList from '~/modules/message/pmList.ducks'; -import userTopicList from '~/modules/user/userTopicList.ducks'; +import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; import friendList from '~/modules/user/friendList/friendList.ducks'; import topicItem from '~/modules/topic/topic/topic.ducks'; import userItem from '~/modules/user/user.ducks'; diff --git a/src/modules/user/userTopicList.ducks.js b/src/modules/user/userTopicList/userTopicList.ducks.js similarity index 72% rename from src/modules/user/userTopicList.ducks.js rename to src/modules/user/userTopicList/userTopicList.ducks.js index 6660827..50bceea 100644 --- a/src/modules/user/userTopicList.ducks.js +++ b/src/modules/user/userTopicList/userTopicList.ducks.js @@ -6,23 +6,23 @@ import { LOGOUT } from '~/modules/user/session.ducks'; // Actions // ********************************* -export const USER_TOPIC_LIST_FETCH = 'USER_TOPIC_LIST_FETCH'; -export const USER_TOPIC_LIST_INVALIDATE = 'USER_TOPIC_LIST_INVALIDATE'; +export const USERTOPICLIST_FETCH = 'USERTOPICLIST_FETCH'; +export const USERTOPICLIST_INVALIDATE = 'USERTOPICLIST_INVALIDATE'; -const USER_TOPIC_LIST_FETCH_REQUEST = 'USER_TOPIC_LIST_FETCH_REQUEST'; -const USER_TOPIC_LIST_FETCH_SUCCESS = 'USER_TOPIC_LIST_FETCH_SUCCESS'; -const USER_TOPIC_LIST_FETCH_FAILURE = 'USER_TOPIC_LIST_FETCH_FAILURE'; +const USERTOPICLIST_FETCH_REQUEST = 'USERTOPICLIST_FETCH_REQUEST'; +const USERTOPICLIST_FETCH_SUCCESS = 'USERTOPICLIST_FETCH_SUCCESS'; +const USERTOPICLIST_FETCH_FAILURE = 'USERTOPICLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchUserTopicList = createAction(USER_TOPIC_LIST_FETCH); -export const invalidateUserTopicList = createAction(USER_TOPIC_LIST_INVALIDATE); +export const fetchUserTopicList = createAction(USERTOPICLIST_FETCH); +export const invalidateUserTopicList = createAction(USERTOPICLIST_INVALIDATE); -export const request = createAction(USER_TOPIC_LIST_FETCH_REQUEST); -export const success = createAction(USER_TOPIC_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(USER_TOPIC_LIST_FETCH_FAILURE, null, (...args) => args[1]); +export const fetchUserTopicListRequest = createAction(USERTOPICLIST_FETCH_REQUEST); +export const fetchUserTopicListSuccess = createAction(USERTOPICLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchUserTopicListFailure = createAction(USERTOPICLIST_FETCH_FAILURE, null, (...args) => args[1]); // ********************************* // Reducer @@ -40,7 +40,7 @@ const defaultUserTopicListState = { }; export default handleActions({ - [USER_TOPIC_LIST_INVALIDATE]: (state, action) => { + [USERTOPICLIST_INVALIDATE]: (state, action) => { let { userId, type } = action.payload; return { ...state, @@ -53,7 +53,7 @@ export default handleActions({ } }; }, - [USER_TOPIC_LIST_FETCH_REQUEST]: (state, action) => { + [USERTOPICLIST_FETCH_REQUEST]: (state, action) => { let { userId, type, isEndReached } = action.payload; return { ...state, @@ -68,7 +68,7 @@ export default handleActions({ } }; }, - [USER_TOPIC_LIST_FETCH_SUCCESS]: (state, action) => { + [USERTOPICLIST_FETCH_SUCCESS]: (state, action) => { let { payload: userTopicList, meta: { @@ -93,7 +93,7 @@ export default handleActions({ } }; }, - [USER_TOPIC_LIST_FETCH_FAILURE]: (state, action) => { + [USERTOPICLIST_FETCH_FAILURE]: (state, action) => { let { userId, type } = action.meta; return { ...state, diff --git a/src/modules/user/userTopicList/userTopicList.epics.js b/src/modules/user/userTopicList/userTopicList.epics.js new file mode 100644 index 0000000..84a7ee1 --- /dev/null +++ b/src/modules/user/userTopicList/userTopicList.epics.js @@ -0,0 +1,40 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map, filter } from 'rxjs/operators'; +import { + USERTOPICLIST_FETCH, + fetchUserTopicListRequest, + fetchUserTopicListSuccess, + fetchUserTopicListFailure +} from './userTopicList.ducks'; +import api from '~/services/api'; +import cacheManager from '~/services/cacheManager'; + +const fetchUserTopicList = (action$, state$) => action$.pipe( + ofType(USERTOPICLIST_FETCH), + filter(action => { + const { userId, type } = action.payload; + return cacheManager.shouldFetchList(state$.value, 'userTopicList', userId, type); + }), + mergeMap(action => + concat( + of(fetchUserTopicListRequest(action.payload)), + fromPromise(api.fetchUserTopicList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchUserTopicListSuccess(data, action.payload); + } else { + return fetchUserTopicListFailure(error, action.payload); + } + }) + ) + ) + ) +); + +export default combineEpics( + fetchUserTopicList +); diff --git a/src/sagas/index.js b/src/sagas/index.js index cd4ab91..0e69d21 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,7 +2,6 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as sessionActions from '~/modules/user/session.ducks'; -import * as userTopicListActions from '~/modules/user/userTopicList.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; @@ -14,7 +13,6 @@ import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); -const fetchUserTopicListApi = fetchResource.bind(null, userTopicListActions, api.fetchUserTopicList); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); @@ -48,24 +46,6 @@ function* watchLogin() { } } -// user topic list sags - -function* watchUserTopicList() { - while(true) { - const { payload } = yield take(userTopicListActions.USER_TOPIC_LIST_FETCH); - yield fork(fetchUserTopicList, payload); - } -} - -function* fetchUserTopicList(payload) { - const state = yield select(); - const { userId, type } = payload; - - if (cacheManager.shouldFetchList(state, 'userTopicList', userId, type)) { - yield fork(fetchUserTopicListApi, payload); - } -} - // notify list sagas function* watchNotifyList() { @@ -134,7 +114,6 @@ function* watchUsers() { export default function* rootSaga() { yield fork(watchRetrieveSession); yield fork(watchLogin); - yield fork(watchUserTopicList); yield fork(watchNotifyList); yield fork(watchPmSessionList); yield fork(watchPmList); From d3b1925aa631b481dc530968843d81bdcbe2c158 Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 28 Aug 2018 22:57:31 +0800 Subject: [PATCH 28/58] refactor: replace redux-saga with redux-observable for user --- src/containers/Information/Information.js | 17 +++-- src/modules/root/rootEpic.js | 2 + src/modules/root/rootReducer.js | 2 +- src/modules/user/user.ducks.js | 83 ----------------------- src/modules/user/user/user.ducks.js | 53 +++++++++++++++ src/modules/user/user/user.epics.js | 33 +++++++++ src/sagas/index.js | 12 ---- 7 files changed, 100 insertions(+), 102 deletions(-) delete mode 100644 src/modules/user/user.ducks.js create mode 100644 src/modules/user/user/user.ducks.js create mode 100644 src/modules/user/user/user.epics.js diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index d450f97..1f5fec5 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -9,7 +9,11 @@ import ImagePicker from '~/services/ImagePicker'; import MENUS from '~/constants/menus'; import api from '~/services/api'; import { setSession } from '~/modules/user/session.ducks'; -import { fetchUser, resetUser } from '~/modules/user/user.ducks'; +import { + fetchUser, + cancelUser, + resetUser +} from '~/modules/user/user/user.ducks'; import mainStyles from '~/common/styles/Main.style'; import indicatorStyles from '~/common/styles/Indicator.style'; @@ -33,7 +37,8 @@ class Information extends Component { } componentWillUnmount() { - this.props.resetUser({ userId: this.userId }); + this.props.cancelUser(); + this.props.resetUser(); } uploadPhoto(image) { @@ -72,14 +77,13 @@ class Information extends Component { render() { let { - userItem, userItem: { isFetching, user } } = this.props; - if (isFetching || !_.get(userItem, ['user', 'name'])) { + if (isFetching || !user) { return ( ); @@ -115,14 +119,15 @@ class Information extends Component { } } -function mapStateToProps({ session, userItem }, ownProps) { +function mapStateToProps({ session, userItem }) { return { loginUserId: _.get(session, ['data', 'uid']), - userItem: _.get(userItem, ownProps.navigation.state.params.userId, {}) + userItem }; } export default connect(mapStateToProps, { fetchUser, + cancelUser, resetUser })(Information); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index b32274d..2f45079 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -5,6 +5,7 @@ import searchList from '~/modules/topic/searchList/searchList.epics'; import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; import friendList from '~/modules/user/friendList/friendList.epics'; import topicItem from '~/modules/topic/topic/topic.epics'; +import userItem from '~/modules/user/user/user.epics'; import settings from '~/modules/settings/settings.epics'; export default combineEpics( @@ -15,6 +16,7 @@ export default combineEpics( friendList, topicItem, + userItem, settings ); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 0f1013e..dad57c2 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -9,7 +9,7 @@ import pmList from '~/modules/message/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; import friendList from '~/modules/user/friendList/friendList.ducks'; import topicItem from '~/modules/topic/topic/topic.ducks'; -import userItem from '~/modules/user/user.ducks'; +import userItem from '~/modules/user/user/user.ducks'; import alert from '~/modules/message/alert.ducks'; import settings from '~/modules/settings/settings.ducks'; diff --git a/src/modules/user/user.ducks.js b/src/modules/user/user.ducks.js deleted file mode 100644 index 3ecf31f..0000000 --- a/src/modules/user/user.ducks.js +++ /dev/null @@ -1,83 +0,0 @@ -import { createAction, handleActions } from 'redux-actions'; -import _ from 'lodash'; - -// ********************************* -// Actions -// ********************************* - -export const USER_FETCH = 'USER_FETCH'; -export const USER_RESET = 'USER_RESET'; - -const USER_FETCH_REQUEST = 'USER_FETCH_REQUEST'; -const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'; -const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE'; - -// ********************************* -// Action Creators -// ********************************* - -export const fetchUser = createAction(USER_FETCH); -export const resetUser = createAction(USER_RESET); - -export const request = createAction(USER_FETCH_REQUEST); -export const success = createAction(USER_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(USER_FETCH_FAILURE); - -// ********************************* -// Reducer -// ********************************* - -const defaultState = {}; -const defaultUserState = { - isFetching: false, - user: {}, - errCode: '' -}; - -export default handleActions({ - [USER_FETCH_REQUEST]: (state, action) => { - let { userId } = action.payload; - return { - ...state, - [userId]: { - isFetching: true, - ..._.get(state, userId, defaultUserState) - } - }; - }, - [USER_FETCH_SUCCESS]: (state, action) => { - let { - payload, - meta: { - userId - } - } = action; - return { - ...state, - [userId]: { - ..._.get(state, userId, defaultUserState), - isFetching: false, - user: payload, - errCode: payload.errcode - } - }; - }, - [USER_FETCH_FAILURE]: (state, action) => { - let { userId } = action.payload; - return { - ...state, - [userId]: { - isFetching: false, - ..._.get(state, userId, defaultUserState) - } - }; - }, - // We didn't cahce user item like topic list, because user information - // will be updated frequently like published/replied post count. - // - // This will be triggerd in `componentWillUnmount()`. - [USER_RESET]: (state, action) => { - let { userId } = action.payload; - return _.pickBy(state, (value, key) => +key !== userId); - } -}, defaultState); diff --git a/src/modules/user/user/user.ducks.js b/src/modules/user/user/user.ducks.js new file mode 100644 index 0000000..c982aa9 --- /dev/null +++ b/src/modules/user/user/user.ducks.js @@ -0,0 +1,53 @@ +import { createAction, handleActions } from 'redux-actions'; + +// ********************************* +// Actions +// ********************************* + +export const USER_FETCH = 'USER_FETCH'; +export const USER_CANCEL = 'USER_CANCEL'; +export const USER_RESET = 'USER_RESET'; + +const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'; +const USER_FETCH_FAILURE = 'USER_FETCH_FAILURE'; + +// ********************************* +// Action Creators +// ********************************* + +export const fetchUser = createAction(USER_FETCH); +export const cancelUser = createAction(USER_CANCEL); +export const resetUser = createAction(USER_RESET); + +export const fetchUserSuccess = createAction(USER_FETCH_SUCCESS); +export const fetchUserFailure = createAction(USER_FETCH_FAILURE); + +// ********************************* +// Reducer +// ********************************* + +const defaultUserState = { + isFetching: false, + user: null +}; + +export default handleActions({ + [USER_FETCH]: (state, action) => ({ + ...state, + isFetching: true + }), + [USER_FETCH_SUCCESS]: (state, action) => ({ + ...state, + isFetching: false, + user: action.payload + }), + [USER_FETCH_FAILURE]: (state, action) => ({ + ...state, + isFetching: false + }), + // We didn't cahce user item like topic list, because user information + // will be updated frequently like published/replied post count. + // + // This will be triggerd in `componentWillUnmount()`. + [USER_RESET]: () => defaultUserState +}, defaultUserState); diff --git a/src/modules/user/user/user.epics.js b/src/modules/user/user/user.epics.js new file mode 100644 index 0000000..a2d94f1 --- /dev/null +++ b/src/modules/user/user/user.epics.js @@ -0,0 +1,33 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map, takeUntil } from 'rxjs/operators'; +import { + USER_FETCH, + USER_CANCEL, + fetchUserSuccess, + fetchUserFailure +} from './user.ducks'; +import api from '~/services/api'; + +const fetchUser = (action$) => action$.pipe( + ofType(USER_FETCH), + mergeMap(action => fromPromise(api.fetchUser(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchUserSuccess(data); + } else { + return fetchUserFailure(error); + } + }), + takeUntil(action$.pipe( + ofType(USER_CANCEL) + )) + )) +); + +export default combineEpics( + fetchUser +); diff --git a/src/sagas/index.js b/src/sagas/index.js index 0e69d21..7d3bc97 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -6,7 +6,6 @@ import * as notifyListActions from '~/modules/message/notifyList.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; -import * as userActions from '~/modules/user/user.ducks'; import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; @@ -17,7 +16,6 @@ const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetch const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); -const fetchUserApi = fetchResource.bind(null, userActions, api.fetchUser); // user login sagas @@ -102,15 +100,6 @@ function* watchAlerts() { } } -// users sagas - -function* watchUsers() { - while(true) { - const { payload } = yield take(userActions.USER_FETCH); - yield fork(fetchUserApi, payload); - } -} - export default function* rootSaga() { yield fork(watchRetrieveSession); yield fork(watchLogin); @@ -118,5 +107,4 @@ export default function* rootSaga() { yield fork(watchPmSessionList); yield fork(watchPmList); yield fork(watchAlerts); - yield fork(watchUsers); } From a2bea4f7559884547a20370d12d0aff1c15ec23c Mon Sep 17 00:00:00 2001 From: just4fun Date: Wed, 29 Aug 2018 23:56:53 +0800 Subject: [PATCH 29/58] refactor: replace redux-saga with redux-observable for session --- src/components/LoginModal/LoginModal.js | 2 +- src/containers/Information/Information.js | 2 +- src/containers/Menu/Menu.js | 2 +- src/containers/Navigator/Navigator.js | 2 +- .../forum/forumList/forumList.ducks.js | 2 +- src/modules/message/alert.ducks.js | 2 +- src/modules/message/notifyList.ducks.js | 2 +- src/modules/message/pmSessionList.ducks.js | 2 +- src/modules/root/rootEpic.js | 4 ++ src/modules/root/rootReducer.js | 3 +- .../topic/topicList/topicList.ducks.js | 2 +- .../user/{ => session}/session.ducks.js | 13 ++---- src/modules/user/session/session.epics.js | 45 +++++++++++++++++++ .../user/userTopicList/userTopicList.ducks.js | 2 +- src/sagas/index.js | 30 ------------- src/services/api.js | 2 +- 16 files changed, 66 insertions(+), 51 deletions(-) rename src/modules/user/{ => session}/session.ducks.js (84%) create mode 100644 src/modules/user/session/session.epics.js diff --git a/src/components/LoginModal/LoginModal.js b/src/components/LoginModal/LoginModal.js index eb3ce45..b00b9ee 100644 --- a/src/components/LoginModal/LoginModal.js +++ b/src/components/LoginModal/LoginModal.js @@ -23,7 +23,7 @@ import { resetSession, resetSessionResult, logout -} from '~/modules/user/session.ducks'; +} from '~/modules/user/session/session.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from './LoginModal.style'; diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index 1f5fec5..f9d5f6e 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -8,7 +8,7 @@ import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import ImagePicker from '~/services/ImagePicker'; import MENUS from '~/constants/menus'; import api from '~/services/api'; -import { setSession } from '~/modules/user/session.ducks'; +import { setSession } from '~/modules/user/session/session.ducks'; import { fetchUser, cancelUser, diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index c868d8d..c21de54 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -17,7 +17,7 @@ import { resetSession, resetSessionResult, logout -} from '~/modules/user/session.ducks'; +} from '~/modules/user/session/session.ducks'; import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; import { getAlertCount } from '~/selectors/alert'; diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index 712792d..2d46a9d 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -21,7 +21,7 @@ import PublishModalScreen from '~/components/PublishModal/PublishModal'; import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; -import { retrieveSessionFromStorage } from '~/modules/user/session.ducks'; +import { retrieveSessionFromStorage } from '~/modules/user/session/session.ducks'; import { retrieveSettingsFromStorage } from '~/modules/settings/settings.ducks'; import { fetchAlert } from '~/modules/message/alert.ducks'; import { ALERT_POLL_FREQUENCY } from '~/config'; diff --git a/src/modules/forum/forumList/forumList.ducks.js b/src/modules/forum/forumList/forumList.ducks.js index 95bc354..92f3ac9 100644 --- a/src/modules/forum/forumList/forumList.ducks.js +++ b/src/modules/forum/forumList/forumList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; import _ from 'lodash'; // ********************************* diff --git a/src/modules/message/alert.ducks.js b/src/modules/message/alert.ducks.js index e98435a..b8e9f73 100644 --- a/src/modules/message/alert.ducks.js +++ b/src/modules/message/alert.ducks.js @@ -6,7 +6,7 @@ import { MARK_SYSTEM_AS_READ } from '~/modules/message/notifyList.ducks'; import { MARK_PM_AS_READ } from '~/modules/message/pmSessionList.ducks'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; // ********************************* // Actions diff --git a/src/modules/message/notifyList.ducks.js b/src/modules/message/notifyList.ducks.js index 806924b..89cb9f6 100644 --- a/src/modules/message/notifyList.ducks.js +++ b/src/modules/message/notifyList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; // ********************************* // Actions diff --git a/src/modules/message/pmSessionList.ducks.js b/src/modules/message/pmSessionList.ducks.js index fe9f316..063507e 100644 --- a/src/modules/message/pmSessionList.ducks.js +++ b/src/modules/message/pmSessionList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; // ********************************* // Actions diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 2f45079..3f54bfd 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -1,4 +1,6 @@ import { combineEpics } from 'redux-observable'; + +import session from '~/modules/user/session/session.epics'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; @@ -9,6 +11,8 @@ import userItem from '~/modules/user/user/user.epics'; import settings from '~/modules/settings/settings.epics'; export default combineEpics( + session, + topicList, forumList, searchList, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index dad57c2..dac9c9e 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -1,5 +1,6 @@ import { combineReducers } from 'redux'; -import session from '~/modules/user/session.ducks'; + +import session from '~/modules/user/session/session.ducks'; import topicList from '~/modules/topic/topicList/topicList.ducks'; import forumList from '~/modules/forum/forumList/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; diff --git a/src/modules/topic/topicList/topicList.ducks.js b/src/modules/topic/topicList/topicList.ducks.js index ac79228..ef09609 100644 --- a/src/modules/topic/topicList/topicList.ducks.js +++ b/src/modules/topic/topicList/topicList.ducks.js @@ -1,5 +1,5 @@ import { createAction, handleActions } from 'redux-actions'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; import _ from 'lodash'; // ********************************* diff --git a/src/modules/user/session.ducks.js b/src/modules/user/session/session.ducks.js similarity index 84% rename from src/modules/user/session.ducks.js rename to src/modules/user/session/session.ducks.js index 6bf93e7..c961eed 100644 --- a/src/modules/user/session.ducks.js +++ b/src/modules/user/session/session.ducks.js @@ -11,7 +11,6 @@ export const SESSION_SET = 'SESSION_SET'; export const SESSION_RESET = 'SESSION_RESET'; export const SESSION_RESULT_RESET = 'SESSION_RESULT_RESET'; -const LOGIN_REQUEST = 'LOGIN_REQUEST'; const LOGIN_SUCCESS = 'LOGIN_SUCCESS'; const LOGIN_FAILURE = 'LOGIN_FAILURE'; @@ -28,9 +27,8 @@ export const setSession = createAction(SESSION_SET); export const resetSession = createAction(SESSION_RESET); export const resetSessionResult = createAction(SESSION_RESULT_RESET); -export const request = createAction(LOGIN_REQUEST); -export const success = createAction(LOGIN_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(LOGIN_FAILURE); +export const loginSuccess = createAction(LOGIN_SUCCESS); +export const loginFailure = createAction(LOGIN_FAILURE); export const logout = createAction(LOGOUT); @@ -50,12 +48,9 @@ export default handleActions({ ...state, data: action.payload }), - [LOGIN_REQUEST]: (state, action) => ({ + [LOGIN]: (state, action) => ({ ...state, - isFetching: true, - data: {}, - hasError: false, - result: false + isFetching: true }), [LOGIN_SUCCESS]: (state, action) => ({ ...state, diff --git a/src/modules/user/session/session.epics.js b/src/modules/user/session/session.epics.js new file mode 100644 index 0000000..ceb7f33 --- /dev/null +++ b/src/modules/user/session/session.epics.js @@ -0,0 +1,45 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { AsyncStorage } from 'react-native'; +import { + LOGIN, + SESSION_RETRIEVE, + loginSuccess, + loginFailure, + setSession +} from './session.ducks'; +import api from '~/services/api'; + +const login = (action$) => action$.pipe( + ofType(LOGIN), + mergeMap(action => fromPromise(api.login(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return loginSuccess(data); + } else { + return loginFailure(error); + } + }) + )) +); + +const retrieveSession = (action$) => action$.pipe( + ofType(SESSION_RETRIEVE), + mergeMap(action => fromPromise(AsyncStorage.getItem('session')).pipe( + map(session => { + if (session) { + session = JSON.parse(session); + return setSession(session); + } + }) + )) +); + +export default combineEpics( + login, + retrieveSession +); diff --git a/src/modules/user/userTopicList/userTopicList.ducks.js b/src/modules/user/userTopicList/userTopicList.ducks.js index 50bceea..adcaaf4 100644 --- a/src/modules/user/userTopicList/userTopicList.ducks.js +++ b/src/modules/user/userTopicList/userTopicList.ducks.js @@ -1,6 +1,6 @@ import { createAction, handleActions } from 'redux-actions'; import _ from 'lodash'; -import { LOGOUT } from '~/modules/user/session.ducks'; +import { LOGOUT } from '~/modules/user/session/session.ducks'; // ********************************* // Actions diff --git a/src/sagas/index.js b/src/sagas/index.js index 7d3bc97..31ac392 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,7 +1,6 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; -import * as sessionActions from '~/modules/user/session.ducks'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as pmListActions from '~/modules/message/pmList.ducks'; @@ -11,38 +10,11 @@ import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; -const fetchLoginUserApi = fetchResource.bind(null, sessionActions, api.fetchLoginUser); const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); -// user login sagas - -function* watchRetrieveSession() { - while(true) { - yield take(sessionActions.SESSION_RETRIEVE); - let session = yield call(retrieveSessionFromStorage); - - if (session) { - session = JSON.parse(session); - yield put(sessionActions.setSession(session)); - } - } -} - -// how to use `yield` inside callback? -// https://github.com/redux-saga/redux-saga/issues/508 -function retrieveSessionFromStorage() { - return new Promise(resolve => AsyncStorage.getItem('session').then(resolve)); -} - -function* watchLogin() { - while(true) { - const { payload } = yield take(sessionActions.LOGIN); - yield fork(fetchLoginUserApi, payload); - } -} // notify list sagas @@ -101,8 +73,6 @@ function* watchAlerts() { } export default function* rootSaga() { - yield fork(watchRetrieveSession); - yield fork(watchLogin); yield fork(watchNotifyList); yield fork(watchPmSessionList); yield fork(watchPmList); diff --git a/src/services/api.js b/src/services/api.js index a709d12..6165cc5 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -97,7 +97,7 @@ function assemblePayload({ // API Methods export default { - fetchLoginUser: ({ + login: ({ userName, password }) => { From d0e42ac92c9fab27fdf868b2901279634a257743 Mon Sep 17 00:00:00 2001 From: just4fun Date: Thu, 30 Aug 2018 01:00:26 +0800 Subject: [PATCH 30/58] refactor: replace redux-saga with redux-observable for pm list --- src/containers/PmList/PmList.js | 5 ++- .../message/{ => pmList}/pmList.ducks.js | 34 +++++++++---------- src/modules/message/pmList/pmList.epics.js | 33 ++++++++++++++++++ src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- src/sagas/index.js | 12 ------- 6 files changed, 57 insertions(+), 31 deletions(-) rename src/modules/message/{ => pmList}/pmList.ducks.js (56%) create mode 100644 src/modules/message/pmList/pmList.epics.js diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index 8dbfe00..ed2fdd5 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -14,9 +14,10 @@ import GiftedChatMessageText from '~/common/vendor/components/GiftedChatMessageT import LoadingSpinner from '~/components/LoadingSpinner/LoadingSpinner'; import { fetchPmList, + cancelPmList, resetPmList, resetPmListResponseStatus -} from '~/modules/message/pmList.ducks'; +} from '~/modules/message/pmList/pmList.ducks'; import { PRIVATE_MESSAGE_POLL_FREQUENCY } from '~/config'; import api from '~/services/api'; @@ -51,6 +52,7 @@ class PmList extends Component { } componentWillUnmount() { + this.props.cancelPmList(); this.props.resetPmList(); // Tear down timer. this.timer && clearInterval(this.timer); @@ -215,6 +217,7 @@ function mapStateToProps({ pmList }) { export default connect(mapStateToProps, { fetchPmList, + cancelPmList, resetPmList, resetPmListResponseStatus })(PmList); diff --git a/src/modules/message/pmList.ducks.js b/src/modules/message/pmList/pmList.ducks.js similarity index 56% rename from src/modules/message/pmList.ducks.js rename to src/modules/message/pmList/pmList.ducks.js index 88087b5..f753c1e 100644 --- a/src/modules/message/pmList.ducks.js +++ b/src/modules/message/pmList/pmList.ducks.js @@ -5,25 +5,25 @@ import _ from 'lodash'; // Actions // ********************************* -export const PM_LIST_FETCH = 'PM_LIST_FETCH'; -export const PM_LIST_RESET = 'PM_LIST_RESET'; -export const PM_LIST_RESPONSE_STATUS_RESET = 'PM_LIST_RESPONSE_STATUS_RESET'; +export const PMLIST_FETCH = 'PMLIST_FETCH'; +export const PMLIST_CANCEL = 'PMLIST_CANCEL'; +export const PMLIST_RESET = 'PMLIST_RESET'; +export const PMLIST_RESPONSE_STATUS_RESET = 'PMLIST_RESPONSE_STATUS_RESET'; -const PM_LIST_FETCH_REQUEST = 'PM_LIST_FETCH_REQUEST'; -const PM_LIST_FETCH_SUCCESS = 'PM_LIST_FETCH_SUCCESS'; -const PM_LIST_FETCH_FAILURE = 'PM_LIST_FETCH_FAILURE'; +const PMLIST_FETCH_SUCCESS = 'PMLIST_FETCH_SUCCESS'; +const PMLIST_FETCH_FAILURE = 'PMLIST_FETCH_FAILURE'; // ********************************* // Action Creators // ********************************* -export const fetchPmList = createAction(PM_LIST_FETCH); -export const resetPmList = createAction(PM_LIST_RESET); -export const resetPmListResponseStatus = createAction(PM_LIST_RESPONSE_STATUS_RESET); +export const fetchPmList = createAction(PMLIST_FETCH); +export const cancelPmList = createAction(PMLIST_CANCEL); +export const resetPmList = createAction(PMLIST_RESET); +export const resetPmListResponseStatus = createAction(PMLIST_RESPONSE_STATUS_RESET); -export const request = createAction(PM_LIST_FETCH_REQUEST); -export const success = createAction(PM_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(PM_LIST_FETCH_FAILURE); +export const fetchPmListSuccess = createAction(PMLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchPmListFailure = createAction(PMLIST_FETCH_FAILURE); // ********************************* // Reducer @@ -40,11 +40,11 @@ const defaultPmListState = { }; export default handleActions({ - [PM_LIST_FETCH_REQUEST]: (state, action) => ({ + [PMLIST_FETCH]: (state, action) => ({ ...state, isRefreshing: true }), - [PM_LIST_FETCH_SUCCESS]: (state, action) => { + [PMLIST_FETCH_SUCCESS]: (state, action) => { let { meta, payload, @@ -78,12 +78,12 @@ export default handleActions({ response: payload }; }, - [PM_LIST_FETCH_FAILURE]: (state, action) => ({ + [PMLIST_FETCH_FAILURE]: (state, action) => ({ ...state, isRefreshing: false }), - [PM_LIST_RESET]: () => defaultPmListState, - [PM_LIST_RESPONSE_STATUS_RESET]: (state, action) => ({ + [PMLIST_RESET]: () => defaultPmListState, + [PMLIST_RESPONSE_STATUS_RESET]: (state, action) => ({ ...state, response: '' }) diff --git a/src/modules/message/pmList/pmList.epics.js b/src/modules/message/pmList/pmList.epics.js new file mode 100644 index 0000000..e17dc8f --- /dev/null +++ b/src/modules/message/pmList/pmList.epics.js @@ -0,0 +1,33 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map, takeUntil } from 'rxjs/operators'; +import { + PMLIST_FETCH, + PMLIST_CANCEL, + fetchPmListSuccess, + fetchPmListFailure +} from './pmList.ducks'; +import api from '~/services/api'; + +const fetchPmList = (action$) => action$.pipe( + ofType(PMLIST_FETCH), + mergeMap(action => fromPromise(api.fetchPmList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchPmListSuccess(data, action.payload); + } else { + return fetchPmListFailure(error); + } + }), + takeUntil(action$.pipe( + ofType(PMLIST_CANCEL) + )) + )) +); + +export default combineEpics( + fetchPmList +); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 3f54bfd..a20adb3 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -4,6 +4,7 @@ import session from '~/modules/user/session/session.epics'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import pmList from '~/modules/message/pmList/pmList.epics'; import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; import friendList from '~/modules/user/friendList/friendList.epics'; import topicItem from '~/modules/topic/topic/topic.epics'; @@ -16,6 +17,7 @@ export default combineEpics( topicList, forumList, searchList, + pmList, userTopicList, friendList, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index dac9c9e..c1cd948 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -6,7 +6,7 @@ import forumList from '~/modules/forum/forumList/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList.ducks'; -import pmList from '~/modules/message/pmList.ducks'; +import pmList from '~/modules/message/pmList/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; import friendList from '~/modules/user/friendList/friendList.ducks'; import topicItem from '~/modules/topic/topic/topic.ducks'; diff --git a/src/sagas/index.js b/src/sagas/index.js index 31ac392..c605379 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -3,7 +3,6 @@ import { take, fork, select, put, call } from 'redux-saga/effects'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; -import * as pmListActions from '~/modules/message/pmList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; import cacheManager from '~/services/cacheManager'; @@ -12,7 +11,6 @@ import api from '~/services/api'; const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); -const fetchPmListApi = fetchResource.bind(null, pmListActions, api.fetchPmList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); @@ -54,15 +52,6 @@ function* fetchPmSessionList(payload) { // } } -// pm list sagas - -function* watchPmList() { - while(true) { - const { payload } = yield take(pmListActions.PM_LIST_FETCH); - yield fork(fetchPmListApi, payload); - } -} - // alerts sagas function* watchAlerts() { @@ -75,6 +64,5 @@ function* watchAlerts() { export default function* rootSaga() { yield fork(watchNotifyList); yield fork(watchPmSessionList); - yield fork(watchPmList); yield fork(watchAlerts); } From e08a6bb2cb117a93c319345f2b8c3e7c5732a062 Mon Sep 17 00:00:00 2001 From: just4fun Date: Thu, 30 Aug 2018 01:11:14 +0800 Subject: [PATCH 31/58] refactor: replace redux-saga with redux-observable for pm session list --- src/containers/Message/Message.js | 2 +- src/modules/message/alert.ducks.js | 2 +- .../pmSessionList.ducks.js | 26 ++++++++--------- .../pmSessionList/pmSessionList.epics.js | 29 +++++++++++++++++++ src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- src/sagas/index.js | 22 -------------- 7 files changed, 46 insertions(+), 39 deletions(-) rename src/modules/message/{ => pmSessionList}/pmSessionList.ducks.js (67%) create mode 100644 src/modules/message/pmSessionList/pmSessionList.epics.js diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index ef32e21..861c5dc 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -9,7 +9,7 @@ import PmSessionList from '~/components/PmSessionList/PmSessionList'; import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList.ducks'; -import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList.ducks'; +import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList/pmSessionList.ducks'; import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/modules/message/alert.ducks.js b/src/modules/message/alert.ducks.js index b8e9f73..57a2a8f 100644 --- a/src/modules/message/alert.ducks.js +++ b/src/modules/message/alert.ducks.js @@ -5,7 +5,7 @@ import { MARK_REPLY_AS_READ, MARK_SYSTEM_AS_READ } from '~/modules/message/notifyList.ducks'; -import { MARK_PM_AS_READ } from '~/modules/message/pmSessionList.ducks'; +import { MARK_PM_AS_READ } from '~/modules/message/pmSessionList/pmSessionList.ducks'; import { LOGOUT } from '~/modules/user/session/session.ducks'; // ********************************* diff --git a/src/modules/message/pmSessionList.ducks.js b/src/modules/message/pmSessionList/pmSessionList.ducks.js similarity index 67% rename from src/modules/message/pmSessionList.ducks.js rename to src/modules/message/pmSessionList/pmSessionList.ducks.js index 063507e..543f5d2 100644 --- a/src/modules/message/pmSessionList.ducks.js +++ b/src/modules/message/pmSessionList/pmSessionList.ducks.js @@ -6,12 +6,11 @@ import { LOGOUT } from '~/modules/user/session/session.ducks'; // Actions // ********************************* -export const PM_SESSION_LIST_FETCH = 'PM_SESSION_LIST_FETCH'; -export const PM_SESSION_LIST_INVALIDATE = 'PM_SESSION_LIST_INVALIDATE'; +export const PMSESSIONLIST_FETCH = 'PMSESSIONLIST_FETCH'; +export const PMSESSIONLIST_INVALIDATE = 'PMSESSIONLIST_INVALIDATE'; -const PM_SESSION_LIST_FETCH_REQUEST = 'PM_SESSION_LIST_FETCH_REQUEST'; -const PM_SESSION_LIST_FETCH_SUCCESS = 'PM_SESSION_LIST_FETCH_SUCCESS'; -const PM_SESSION_LIST_FETCH_FAILURE = 'PM_SESSION_LIST_FETCH_FAILURE'; +const PMSESSIONLIST_FETCH_SUCCESS = 'PMSESSIONLIST_FETCH_SUCCESS'; +const PMSESSIONLIST_FETCH_FAILURE = 'PMSESSIONLIST_FETCH_FAILURE'; export const MARK_PM_AS_READ = 'MARK_PM_AS_READ'; @@ -19,14 +18,13 @@ export const MARK_PM_AS_READ = 'MARK_PM_AS_READ'; // Action Creators // ********************************* -export const fetchPmSessionList = createAction(PM_SESSION_LIST_FETCH); -export const invalidatePmSessionList = createAction(PM_SESSION_LIST_INVALIDATE); +export const fetchPmSessionList = createAction(PMSESSIONLIST_FETCH); +export const invalidatePmSessionList = createAction(PMSESSIONLIST_INVALIDATE); export const markPmAsRead = createAction(MARK_PM_AS_READ); -export const request = createAction(PM_SESSION_LIST_FETCH_REQUEST); -export const success = createAction(PM_SESSION_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(PM_SESSION_LIST_FETCH_FAILURE, null, (...args) => args[1]); +export const fetchPmSessionListSuccess = createAction(PMSESSIONLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchPmSessionListFailure = createAction(PMSESSIONLIST_FETCH_FAILURE); // ********************************* // Reducer @@ -43,7 +41,7 @@ const defaultPmSessionListState = { }; export default handleActions({ - [PM_SESSION_LIST_INVALIDATE]: (state, action) => ({ + [PMSESSIONLIST_INVALIDATE]: (state, action) => ({ ...state, didInvalidate: true }), @@ -59,7 +57,7 @@ export default handleActions({ }) }; }, - [PM_SESSION_LIST_FETCH_REQUEST]: (state, action) => { + [PMSESSIONLIST_FETCH]: (state, action) => { let { isEndReached } = action.payload; return { ...state, @@ -68,7 +66,7 @@ export default handleActions({ didInvalidate: false }; }, - [PM_SESSION_LIST_FETCH_SUCCESS]: (state, action) => { + [PMSESSIONLIST_FETCH_SUCCESS]: (state, action) => { let { meta, payload, @@ -88,7 +86,7 @@ export default handleActions({ errCode: payload.errcode }; }, - [PM_SESSION_LIST_FETCH_FAILURE]: (state, action) => ({ + [PMSESSIONLIST_FETCH_FAILURE]: (state, action) => ({ ...state, isRefreshing: false, isEndReached: false, diff --git a/src/modules/message/pmSessionList/pmSessionList.epics.js b/src/modules/message/pmSessionList/pmSessionList.epics.js new file mode 100644 index 0000000..7733d19 --- /dev/null +++ b/src/modules/message/pmSessionList/pmSessionList.epics.js @@ -0,0 +1,29 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + PMSESSIONLIST_FETCH, + fetchPmSessionListSuccess, + fetchPmSessionListFailure +} from './pmSessionList.ducks'; +import api from '~/services/api'; + +const fetchPmSessionList = (action$) => action$.pipe( + ofType(PMSESSIONLIST_FETCH), + mergeMap(action => fromPromise(api.fetchPmSessionList(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchPmSessionListSuccess(data, action.payload); + } else { + return fetchPmSessionListFailure(error); + } + }) + )) +); + +export default combineEpics( + fetchPmSessionList +); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index a20adb3..3180ec6 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -4,6 +4,7 @@ import session from '~/modules/user/session/session.epics'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.epics'; import pmList from '~/modules/message/pmList/pmList.epics'; import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; import friendList from '~/modules/user/friendList/friendList.epics'; @@ -17,6 +18,7 @@ export default combineEpics( topicList, forumList, searchList, + pmSessionList, pmList, userTopicList, friendList, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index c1cd948..acebab4 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -5,7 +5,7 @@ import topicList from '~/modules/topic/topicList/topicList.ducks'; import forumList from '~/modules/forum/forumList/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList.ducks'; -import pmSessionList from '~/modules/message/pmSessionList.ducks'; +import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.ducks'; import pmList from '~/modules/message/pmList/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; import friendList from '~/modules/user/friendList/friendList.ducks'; diff --git a/src/sagas/index.js b/src/sagas/index.js index c605379..0967f2d 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,7 +2,6 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; -import * as pmSessionListActions from '~/modules/message/pmSessionList.ducks'; import * as alertActions from '~/modules/message/alert.ducks'; import cacheManager from '~/services/cacheManager'; @@ -10,7 +9,6 @@ import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); -const fetchPmSessionListApi = fetchResource.bind(null, pmSessionListActions, api.fetchPmSessionList); const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); @@ -33,25 +31,6 @@ function* fetchNotifyList(payload) { // } } -// pm session list sagas - -function* watchPmSessionList() { - while(true) { - const { payload } = yield take(pmSessionListActions.PM_SESSION_LIST_FETCH); - yield fork(fetchPmSessionList, payload); - } -} - -function* fetchPmSessionList(payload) { - const state = yield select(); - - // Let user fetch private messages immediately. - - // if (cacheManager.shouldFetchList(state, 'pmSessionList')) { - yield fork(fetchPmSessionListApi, payload); - // } -} - // alerts sagas function* watchAlerts() { @@ -63,6 +42,5 @@ function* watchAlerts() { export default function* rootSaga() { yield fork(watchNotifyList); - yield fork(watchPmSessionList); yield fork(watchAlerts); } From 7fdced9e747a989c9e745211ad9954a8a686b6b2 Mon Sep 17 00:00:00 2001 From: just4fun Date: Thu, 30 Aug 2018 01:19:38 +0800 Subject: [PATCH 32/58] refactor: replace redux-saga with redux-observable for alert --- src/containers/Navigator/Navigator.js | 2 +- src/containers/Settings/Settings.js | 2 +- .../message/{ => alert}/alert.ducks.js | 8 ++--- src/modules/message/alert/alert.epics.js | 29 +++++++++++++++++++ src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- src/sagas/index.js | 12 -------- 7 files changed, 37 insertions(+), 20 deletions(-) rename src/modules/message/{ => alert}/alert.ducks.js (87%) create mode 100644 src/modules/message/alert/alert.epics.js diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index 2d46a9d..c538b3f 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -23,7 +23,7 @@ import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; import { retrieveSessionFromStorage } from '~/modules/user/session/session.ducks'; import { retrieveSettingsFromStorage } from '~/modules/settings/settings.ducks'; -import { fetchAlert } from '~/modules/message/alert.ducks'; +import { fetchAlert } from '~/modules/message/alert/alert.ducks'; import { ALERT_POLL_FREQUENCY } from '~/config'; import colors from '~/common/styles/colors.style'; diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 2788710..515831b 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -14,7 +14,7 @@ import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; import { storeSettingsToStorage } from '~/modules/settings/settings.ducks'; -import { resetAlert } from '~/modules/message/alert.ducks'; +import { resetAlert } from '~/modules/message/alert/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from '~/containers/Settings/Settings.style'; diff --git a/src/modules/message/alert.ducks.js b/src/modules/message/alert/alert.ducks.js similarity index 87% rename from src/modules/message/alert.ducks.js rename to src/modules/message/alert/alert.ducks.js index 57a2a8f..fe1e02c 100644 --- a/src/modules/message/alert.ducks.js +++ b/src/modules/message/alert/alert.ducks.js @@ -15,7 +15,6 @@ import { LOGOUT } from '~/modules/user/session/session.ducks'; export const ALERT_FETCH = 'ALERT_FETCH'; export const ALERT_RESET = 'ALERT_RESET'; -const ALERT_FETCH_REQUEST = 'ALERT_FETCH_REQUEST'; const ALERT_FETCH_SUCCESS = 'ALERT_FETCH_SUCCESS'; const ALERT_FETCH_FAILURE = 'ALERT_FETCH_FAILURE'; @@ -26,9 +25,8 @@ const ALERT_FETCH_FAILURE = 'ALERT_FETCH_FAILURE'; export const fetchAlert = createAction(ALERT_FETCH); export const resetAlert = createAction(ALERT_RESET); -export const request = createAction(ALERT_FETCH_REQUEST); -export const success = createAction(ALERT_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(ALERT_FETCH_FAILURE); +export const fetchAlertSuccess = createAction(ALERT_FETCH_SUCCESS); +export const fetchAlertFailure = createAction(ALERT_FETCH_FAILURE); // ********************************* // Reducer @@ -45,7 +43,7 @@ const defaultAlertState = { }; export default handleActions({ - [ALERT_FETCH_REQUEST]: (state, action) => ({ + [ALERT_FETCH]: (state, action) => ({ ...state, isFetching: true }), diff --git a/src/modules/message/alert/alert.epics.js b/src/modules/message/alert/alert.epics.js new file mode 100644 index 0000000..fc524db --- /dev/null +++ b/src/modules/message/alert/alert.epics.js @@ -0,0 +1,29 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + ALERT_FETCH, + fetchAlertSuccess, + fetchAlertFailure +} from './alert.ducks'; +import api from '~/services/api'; + +const fetchAlert = (action$) => action$.pipe( + ofType(ALERT_FETCH), + mergeMap(action => fromPromise(api.fetchAlert(action.payload)).pipe( + map(({ + data, + error + }) => { + if (!error) { + return fetchAlertSuccess(data); + } else { + return fetchAlertFailure(error); + } + }) + )) +); + +export default combineEpics( + fetchAlert +); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 3180ec6..5bc0fe2 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -10,6 +10,7 @@ import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; import friendList from '~/modules/user/friendList/friendList.epics'; import topicItem from '~/modules/topic/topic/topic.epics'; import userItem from '~/modules/user/user/user.epics'; +import alert from '~/modules/message/alert/alert.epics'; import settings from '~/modules/settings/settings.epics'; export default combineEpics( @@ -26,5 +27,6 @@ export default combineEpics( topicItem, userItem, + alert, settings ); diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index acebab4..f1f6495 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -11,7 +11,7 @@ import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; import friendList from '~/modules/user/friendList/friendList.ducks'; import topicItem from '~/modules/topic/topic/topic.ducks'; import userItem from '~/modules/user/user/user.ducks'; -import alert from '~/modules/message/alert.ducks'; +import alert from '~/modules/message/alert/alert.ducks'; import settings from '~/modules/settings/settings.ducks'; export default combineReducers({ diff --git a/src/sagas/index.js b/src/sagas/index.js index 0967f2d..ab18dde 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -2,14 +2,12 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; import * as notifyListActions from '~/modules/message/notifyList.ducks'; -import * as alertActions from '~/modules/message/alert.ducks'; import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); -const fetchAlertApi = fetchResource.bind(null, alertActions, api.fetchAlert); // notify list sagas @@ -31,16 +29,6 @@ function* fetchNotifyList(payload) { // } } -// alerts sagas - -function* watchAlerts() { - while(true) { - const { payload } = yield take(alertActions.ALERT_FETCH); - yield fork(fetchAlertApi, payload); - } -} - export default function* rootSaga() { yield fork(watchNotifyList); - yield fork(watchAlerts); } From bab5a325f1d0e79fd945d25df817b2942542314e Mon Sep 17 00:00:00 2001 From: just4fun Date: Thu, 30 Aug 2018 01:22:58 +0800 Subject: [PATCH 33/58] fix: fetch alert immediately once alert toggle opened --- src/containers/Settings/Settings.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 515831b..af38ea1 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -14,7 +14,7 @@ import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; import { storeSettingsToStorage } from '~/modules/settings/settings.ducks'; -import { resetAlert } from '~/modules/message/alert/alert.ducks'; +import { fetchAlert, resetAlert } from '~/modules/message/alert/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; import styles from '~/containers/Settings/Settings.style'; @@ -39,8 +39,12 @@ class Settings extends Component { handleNotificationValueChange(value) { this.props.storeSettingsToStorage({ enableNotification: value }); - // Clear message alters. - this.props.resetAlert(); + + if (value) { + this.props.fetchAlert(); + } else { + this.props.resetAlert(); + } } handlePublishDialogValueChange(value) { @@ -90,5 +94,6 @@ function mapStateToProps({ settings }) { export default connect(mapStateToProps, { storeSettingsToStorage, + fetchAlert, resetAlert })(Settings); From f5536ccd644017f8de3e3fe8f45e0b806792fb11 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 01:04:05 +0800 Subject: [PATCH 34/58] refactor: replace redux-saga with redux-observable for notify list --- src/containers/Message/Message.js | 2 +- src/modules/message/alert/alert.ducks.js | 2 +- .../{ => notifyList}/notifyList.ducks.js | 30 ++++++++-------- .../message/notifyList/notifyList.epics.js | 34 +++++++++++++++++++ src/modules/root/rootEpic.js | 2 ++ src/modules/root/rootReducer.js | 2 +- src/sagas/index.js | 26 +------------- 7 files changed, 54 insertions(+), 44 deletions(-) rename src/modules/message/{ => notifyList}/notifyList.ducks.js (75%) create mode 100644 src/modules/message/notifyList/notifyList.epics.js diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index 861c5dc..a856525 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -8,7 +8,7 @@ import NotifyList from '~/components/NotifyList/NotifyList'; import PmSessionList from '~/components/PmSessionList/PmSessionList'; import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; -import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList.ducks'; +import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList/notifyList.ducks'; import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList/pmSessionList.ducks'; import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; diff --git a/src/modules/message/alert/alert.ducks.js b/src/modules/message/alert/alert.ducks.js index fe1e02c..19a8903 100644 --- a/src/modules/message/alert/alert.ducks.js +++ b/src/modules/message/alert/alert.ducks.js @@ -4,7 +4,7 @@ import { MARK_AT_ME_AS_READ, MARK_REPLY_AS_READ, MARK_SYSTEM_AS_READ -} from '~/modules/message/notifyList.ducks'; +} from '~/modules/message/notifyList/notifyList.ducks'; import { MARK_PM_AS_READ } from '~/modules/message/pmSessionList/pmSessionList.ducks'; import { LOGOUT } from '~/modules/user/session/session.ducks'; diff --git a/src/modules/message/notifyList.ducks.js b/src/modules/message/notifyList/notifyList.ducks.js similarity index 75% rename from src/modules/message/notifyList.ducks.js rename to src/modules/message/notifyList/notifyList.ducks.js index 89cb9f6..810d3f6 100644 --- a/src/modules/message/notifyList.ducks.js +++ b/src/modules/message/notifyList/notifyList.ducks.js @@ -6,12 +6,11 @@ import { LOGOUT } from '~/modules/user/session/session.ducks'; // Actions // ********************************* -export const NOTIFY_LIST_FETCH = 'NOTIFY_LIST_FETCH'; -export const NOTIFY_LIST_INVALIDATE = 'NOTIFY_LIST_INVALIDATE'; +export const NOTIFYLIST_FETCH = 'NOTIFYLIST_FETCH'; +export const NOTIFYLIST_INVALIDATE = 'NOTIFYLIST_INVALIDATE'; -const NOTIFY_LIST_FETCH_REQUEST = 'NOTIFY_LIST_FETCH_REQUEST'; -const NOTIFY_LIST_FETCH_SUCCESS = 'NOTIFY_LIST_FETCH_SUCCESS'; -const NOTIFY_LIST_FETCH_FAILURE = 'NOTIFY_LIST_FETCH_FAILURE'; +export const NOTIFYLIST_FETCH_SUCCESS = 'NOTIFYLIST_FETCH_SUCCESS'; +const NOTIFYLIST_FETCH_FAILURE = 'NOTIFYLIST_FETCH_FAILURE'; export const MARK_AT_ME_AS_READ = 'MARK_AT_ME_AS_READ'; export const MARK_REPLY_AS_READ = 'MARK_REPLY_AS_READ'; @@ -21,8 +20,11 @@ export const MARK_SYSTEM_AS_READ = 'MARK_SYSTEM_AS_READ'; // Action Creators // ********************************* -export const fetchNotifyList = createAction(NOTIFY_LIST_FETCH); -export const invalidateNotifyList = createAction(NOTIFY_LIST_INVALIDATE); +export const fetchNotifyList = createAction(NOTIFYLIST_FETCH); +export const invalidateNotifyList = createAction(NOTIFYLIST_INVALIDATE); + +export const fetchNotifyListSuccess = createAction(NOTIFYLIST_FETCH_SUCCESS, null, (...args) => args[1]); +export const fetchNotifyListFailure = createAction(NOTIFYLIST_FETCH_FAILURE, null, (...args) => args[1]); const markAtMeAsRead = createAction(MARK_AT_ME_AS_READ); const markReplyAsRead = createAction(MARK_REPLY_AS_READ); @@ -30,7 +32,7 @@ const markSystemAsRead = createAction(MARK_SYSTEM_AS_READ); // Update unread message count immediately instead of // clearing them with next poll after 0 ~ 15s. -export const successfulCallback = (payload) => { +export const fetchNotifyListSuccessfulCallback = (payload) => { switch (payload.notifyType) { case 'at': return markAtMeAsRead(); @@ -41,10 +43,6 @@ export const successfulCallback = (payload) => { } } -export const request = createAction(NOTIFY_LIST_FETCH_REQUEST); -export const success = createAction(NOTIFY_LIST_FETCH_SUCCESS, null, (...args) => args[1]); -export const failure = createAction(NOTIFY_LIST_FETCH_FAILURE, null, (...args) => args[1]); - // ********************************* // Reducer // ********************************* @@ -62,7 +60,7 @@ const defaultNotifyListState = { }; export default handleActions({ - [NOTIFY_LIST_INVALIDATE]: (state, action) => { + [NOTIFYLIST_INVALIDATE]: (state, action) => { let { notifyType } = action.payload; return { ...state, @@ -72,7 +70,7 @@ export default handleActions({ } }; }, - [NOTIFY_LIST_FETCH_REQUEST]: (state, action) => { + [NOTIFYLIST_FETCH]: (state, action) => { let { notifyType, isEndReached } = action.payload; return { ...state, @@ -84,7 +82,7 @@ export default handleActions({ } }; }, - [NOTIFY_LIST_FETCH_SUCCESS]: (state, action) => { + [NOTIFYLIST_FETCH_SUCCESS]: (state, action) => { let { payload: notifyList, meta: { @@ -112,7 +110,7 @@ export default handleActions({ } }; }, - [NOTIFY_LIST_FETCH_FAILURE]: (state, action) => { + [NOTIFYLIST_FETCH_FAILURE]: (state, action) => { let { notifyType } = action.meta; return { ...state, diff --git a/src/modules/message/notifyList/notifyList.epics.js b/src/modules/message/notifyList/notifyList.epics.js new file mode 100644 index 0000000..c26fb24 --- /dev/null +++ b/src/modules/message/notifyList/notifyList.epics.js @@ -0,0 +1,34 @@ +import { combineEpics, ofType } from 'redux-observable'; +import { from as fromPromise, of, concat } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { + NOTIFYLIST_FETCH, + NOTIFYLIST_FETCH_SUCCESS, + fetchNotifyListSuccess, + fetchNotifyListFailure, + fetchNotifyListSuccessfulCallback +} from './notifyList.ducks'; +import api from '~/services/api'; + +const fetchNotifyList = (action$) => action$.pipe( + ofType(NOTIFYLIST_FETCH), + mergeMap(action => fromPromise(api.fetchNotifyList(action.payload)).pipe( + mergeMap(({ + data, + error + }) => { + if (!error) { + return concat( + of(fetchNotifyListSuccess(data, action.payload)), + of(fetchNotifyListSuccessfulCallback(action.payload)) + ); + } else { + return fetchNotifyListFailure(error, action.payload); + } + }) + )) +); + +export default combineEpics( + fetchNotifyList +); diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 5bc0fe2..41f3533 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -4,6 +4,7 @@ import session from '~/modules/user/session/session.epics'; import topicList from '~/modules/topic/topicList/topicList.epics'; import forumList from '~/modules/forum/forumList/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; +import notifyList from '~/modules/message/notifyList/notifyList.epics'; import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.epics'; import pmList from '~/modules/message/pmList/pmList.epics'; import userTopicList from '~/modules/user/userTopicList/userTopicList.epics'; @@ -19,6 +20,7 @@ export default combineEpics( topicList, forumList, searchList, + notifyList, pmSessionList, pmList, userTopicList, diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index f1f6495..28cefd9 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -4,7 +4,7 @@ import session from '~/modules/user/session/session.ducks'; import topicList from '~/modules/topic/topicList/topicList.ducks'; import forumList from '~/modules/forum/forumList/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; -import notifyList from '~/modules/message/notifyList.ducks'; +import notifyList from '~/modules/message/notifyList/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.ducks'; import pmList from '~/modules/message/pmList/pmList.ducks'; import userTopicList from '~/modules/user/userTopicList/userTopicList.ducks'; diff --git a/src/sagas/index.js b/src/sagas/index.js index ab18dde..ce6a277 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,34 +1,10 @@ import { AsyncStorage } from 'react-native'; import { take, fork, select, put, call } from 'redux-saga/effects'; -import * as notifyListActions from '~/modules/message/notifyList.ducks'; - import cacheManager from '~/services/cacheManager'; import { fetchResource } from '~/utils/sagaHelper'; import api from '~/services/api'; -const fetchNotifyListApi = fetchResource.bind(null, notifyListActions, api.fetchNotifyList); - - -// notify list sagas - -function* watchNotifyList() { - while(true) { - const { payload } = yield take(notifyListActions.NOTIFY_LIST_FETCH); - yield fork(fetchNotifyList, payload); - } -} - -function* fetchNotifyList(payload) { - // const state = yield select(); - - // Let user fetch notifications immediately. - - // if (cacheManager.shouldFetchList(state, 'notifyList', payload.notifyType)) { - yield fork(fetchNotifyListApi, payload); - // } -} - export default function* rootSaga() { - yield fork(watchNotifyList); + } From e7779ee36091ec8eb14f1067fbc88fd908db51a6 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 01:11:14 +0800 Subject: [PATCH 35/58] refactor: remove redux-saga package and helper --- README.md | 1 - package.json | 1 - src/containers/App/App.js | 2 -- src/sagas/index.js | 10 ---------- src/store/configureStore.js | 4 ---- src/utils/sagaHelper.js | 16 ---------------- yarn.lock | 4 ---- 7 files changed, 38 deletions(-) delete mode 100644 src/sagas/index.js delete mode 100644 src/utils/sagaHelper.js diff --git a/README.md b/README.md index 5cb766f..968638a 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,6 @@ npm run eslint - ~~Update UI per new design~~ - ~~Submit to [App Store](https://itunes.apple.com/cn/app/qing-shui-he-pan-stuhome/id1190564355)~~ -- ~~Replace [redux-thunk](https://github.com/gaearon/redux-thunk) with [redux-saga](https://github.com/redux-saga/redux-saga)~~ ([#7](https://github.com/just4fun/stuhome/pull/7)) - ~~Unit Testing Infrastructure~~ ([#8](https://github.com/just4fun/stuhome/pull/8)) - ~~Replace deprecated Navigator with [React Navigation](https://github.com/react-navigation/react-navigation)~~ ([#19](https://github.com/just4fun/stuhome/pull/19)) diff --git a/package.json b/package.json index 1e6dace..f3635a0 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "redux": "3.3.1", "redux-actions": "1.2.1", "redux-observable": "^1.0.0", - "redux-saga": "0.12.0", "rxjs": "^6.2.2" }, "devDependencies": { diff --git a/src/containers/App/App.js b/src/containers/App/App.js index 58f6734..e11f26d 100644 --- a/src/containers/App/App.js +++ b/src/containers/App/App.js @@ -1,12 +1,10 @@ import React, { Component } from 'react'; import { Provider } from 'react-redux'; import configureStore from '~/store/configureStore'; -import rootSaga from '~/sagas'; import rootEpic from '~/modules/root/rootEpic'; import Navigator from '~/containers/Navigator/Navigator'; const store = configureStore(); -store.runSaga(rootSaga); store.runEpic(rootEpic); export default class App extends Component { diff --git a/src/sagas/index.js b/src/sagas/index.js deleted file mode 100644 index ce6a277..0000000 --- a/src/sagas/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import { AsyncStorage } from 'react-native'; -import { take, fork, select, put, call } from 'redux-saga/effects'; - -import cacheManager from '~/services/cacheManager'; -import { fetchResource } from '~/utils/sagaHelper'; -import api from '~/services/api'; - -export default function* rootSaga() { - -} diff --git a/src/store/configureStore.js b/src/store/configureStore.js index cfa4f92..4b3fd6b 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,14 +1,11 @@ import { createStore, applyMiddleware, compose } from 'redux'; -import createSagaMiddleware from 'redux-saga'; import { createEpicMiddleware } from 'redux-observable'; import rootReducer from '~/modules/root/rootReducer'; -const sagaMiddleware = createSagaMiddleware(); const epicMiddleware = createEpicMiddleware(); export default function configureStore(initialState = {}) { const middlewares = [ - sagaMiddleware, epicMiddleware ]; @@ -22,7 +19,6 @@ export default function configureStore(initialState = {}) { compose(...enhancers) ); - store.runSaga = sagaMiddleware.run; store.runEpic = epicMiddleware.run; return store; diff --git a/src/utils/sagaHelper.js b/src/utils/sagaHelper.js deleted file mode 100644 index 13af14a..0000000 --- a/src/utils/sagaHelper.js +++ /dev/null @@ -1,16 +0,0 @@ -import { call, put } from 'redux-saga/effects'; - -export function* fetchResource(resource, api, payload) { - yield put(resource.request(payload)); - const { data, error } = yield call(api, payload); - - if (!error) { - // The 2nd argument will be treated as `meta` field. - yield put(resource.success(data, payload)); - if (resource.successfulCallback) { - yield put(resource.successfulCallback(payload)); - } - } else { - yield put(resource.failure(error, payload)); - } -} diff --git a/yarn.lock b/yarn.lock index 7dbfe45..7c02dfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4210,10 +4210,6 @@ redux-observable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91" -redux-saga@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.12.0.tgz#4b6145e6f8c33a6082f7d18f30ab5d2901e621e8" - redux@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/redux/-/redux-3.3.1.tgz#716df8004786deaf01c93ae396c84fc1041e424b" From 518dfc357b75933f1b4d3726a9ea2eec9820d5bb Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 01:33:49 +0800 Subject: [PATCH 36/58] docs: explain why we still need `TOPIC_RESET` action --- src/containers/TopicDetail/TopicDetail.js | 1 - src/modules/topic/topic/topic.ducks.js | 22 ++++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 74379d1..38bebb8 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -113,7 +113,6 @@ class TopicDetail extends Component { AlertIOS.alert('提示', topicItem.errCode); nextProps.resetTopic({ topicId: this.topicId }); nextProps.navigation.goBack(); - return; } } diff --git a/src/modules/topic/topic/topic.ducks.js b/src/modules/topic/topic/topic.ducks.js index fac07aa..09dc67b 100644 --- a/src/modules/topic/topic/topic.ducks.js +++ b/src/modules/topic/topic/topic.ducks.js @@ -56,7 +56,7 @@ export const fetchTopicFailure = createAction(TOPIC_FETCH_FAILURE); // page's `componentWillUnmount`. // ********************************* -// Any disadvantages if we don's reset/clear the topic content? +// Any disadvantages if we don't reset/clear the topic content? // ********************************* // // The only disadvantage of not resetting topic item is that, if we navigate from @@ -64,6 +64,17 @@ export const fetchTopicFailure = createAction(TOPIC_FETCH_FAILURE); // with loading spinner before the page transition since we trigger request action // for topic A again. As tradeoff, I think it's not big deal. +// ********************************* +// Why there is still `TOPIC_RESET` action? +// ********************************* +// +// 1. Before we display login modal instead when user clicks topic in home page +// without credentials, this action was used to reset the topic which we have no +// access. +// +// 2. Even we login, there are still topics we have no access, such as the topics +// in some specific forums like `版主交流`. + // ********************************* // Is there race condition? // ********************************* @@ -71,8 +82,8 @@ export const fetchTopicFailure = createAction(TOPIC_FETCH_FAILURE); // There is also no race condition if we use key-value for each topic in redux store. // https://github.com/just4fun/stuhome/issues/25 // -// So we have no need to use `takeUntil` to cancel fetch request when we leave the page -// before response back. But we need to do it in search page becasue we won't send request +// So we also have no need to use `takeUntil` to cancel fetch request when we leave the page +// before response back. But we need to do it in search page because we won't send request // when we access search page and it may display previous search result without cancelling. const defaultState = {}; @@ -145,11 +156,6 @@ export default handleActions({ } }; }, - // This will only be triggerd if we get any error for topic item. - // - // Since the login modal will be displayed if the user clicks topic - // in home page without credentials instead of triggering this action, - // seems like it's useless now, but I'd like to leave it here. [TOPIC_RESET]: (state, action) => { let { topicId } = action.payload; return _.pickBy(state, (value, key) => +key !== +topicId); From c829c1ee5df60772922c9baf1de6f25933688808 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 01:38:49 +0800 Subject: [PATCH 37/58] refactor: move unique forum stuff (forumList) to the top of forum module --- src/components/ForumListModal/ForumListModal.js | 2 +- src/containers/ForumDetail/ForumDetail.js | 2 +- src/containers/ForumList/ForumList.js | 2 +- src/modules/forum/{forumList => }/forumList.ducks.js | 0 src/modules/forum/{forumList => }/forumList.epics.js | 0 src/modules/root/rootEpic.js | 2 +- src/modules/root/rootReducer.js | 2 +- 7 files changed, 5 insertions(+), 5 deletions(-) rename src/modules/forum/{forumList => }/forumList.ducks.js (100%) rename src/modules/forum/{forumList => }/forumList.epics.js (100%) diff --git a/src/components/ForumListModal/ForumListModal.js b/src/components/ForumListModal/ForumListModal.js index fa5d0b6..b595246 100644 --- a/src/components/ForumListModal/ForumListModal.js +++ b/src/components/ForumListModal/ForumListModal.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import Header from '~/components/Header/Header'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import modalStyles from '~/common/styles/Modal.style'; diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 89c5439..217e2e1 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -12,7 +12,7 @@ import ForumItems from '~/components/ForumItems/ForumItems'; import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList/topicList.ducks'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index 8535bad..f129aa8 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -8,7 +8,7 @@ import { import _ from 'lodash'; import ForumItems from '~/components/ForumItems/ForumItems'; import MENUS from '~/constants/menus'; -import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList/forumList.ducks'; +import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/modules/forum/forumList/forumList.ducks.js b/src/modules/forum/forumList.ducks.js similarity index 100% rename from src/modules/forum/forumList/forumList.ducks.js rename to src/modules/forum/forumList.ducks.js diff --git a/src/modules/forum/forumList/forumList.epics.js b/src/modules/forum/forumList.epics.js similarity index 100% rename from src/modules/forum/forumList/forumList.epics.js rename to src/modules/forum/forumList.epics.js diff --git a/src/modules/root/rootEpic.js b/src/modules/root/rootEpic.js index 41f3533..a4e9ffd 100644 --- a/src/modules/root/rootEpic.js +++ b/src/modules/root/rootEpic.js @@ -2,7 +2,7 @@ import { combineEpics } from 'redux-observable'; import session from '~/modules/user/session/session.epics'; import topicList from '~/modules/topic/topicList/topicList.epics'; -import forumList from '~/modules/forum/forumList/forumList.epics'; +import forumList from '~/modules/forum/forumList.epics'; import searchList from '~/modules/topic/searchList/searchList.epics'; import notifyList from '~/modules/message/notifyList/notifyList.epics'; import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.epics'; diff --git a/src/modules/root/rootReducer.js b/src/modules/root/rootReducer.js index 28cefd9..2fae76e 100644 --- a/src/modules/root/rootReducer.js +++ b/src/modules/root/rootReducer.js @@ -2,7 +2,7 @@ import { combineReducers } from 'redux'; import session from '~/modules/user/session/session.ducks'; import topicList from '~/modules/topic/topicList/topicList.ducks'; -import forumList from '~/modules/forum/forumList/forumList.ducks'; +import forumList from '~/modules/forum/forumList.ducks'; import searchList from '~/modules/topic/searchList/searchList.ducks'; import notifyList from '~/modules/message/notifyList/notifyList.ducks'; import pmSessionList from '~/modules/message/pmSessionList/pmSessionList.ducks'; From 1576cb1002fdd2735166be2c145a7bc6835f6dc7 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 01:45:05 +0800 Subject: [PATCH 38/58] refactor: move selectors to the same folder with ducks and epics --- src/containers/Home/Home.js | 2 +- src/containers/Menu/Menu.js | 2 +- src/containers/Message/Message.js | 2 +- .../alert.js => modules/message/alert/alert.selectors.js} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/{selectors/alert.js => modules/message/alert/alert.selectors.js} (100%) diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index 097b717..4a07a16 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -11,7 +11,7 @@ import TopicList from '~/components/TopicList/TopicList'; import MenuButton from '~/components/MenuButton/MenuButton'; import PublishButton from '~/components/PublishButton/PublishButton'; import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; -import { getAlertCount } from '~/selectors/alert'; +import { getAlertCount } from '~/modules/message/alert/alert.selectors'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; import mainStyles from '~/common/styles/Main.style'; diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index c21de54..6f3af9c 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -19,7 +19,7 @@ import { logout } from '~/modules/user/session/session.ducks'; import { invalidateTopicList, fetchTopicList } from '~/modules/topic/topicList/topicList.ducks'; -import { getAlertCount } from '~/selectors/alert'; +import { getAlertCount } from '~/modules/message/alert/alert.selectors'; import styles from './Menu.style'; diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index a856525..fe155da 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -10,7 +10,7 @@ import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList/notifyList.ducks'; import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList/pmSessionList.ducks'; -import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/selectors/alert'; +import { getAtMeCount, getReplyCount, getPmCount, getSystemCount } from '~/modules/message/alert/alert.selectors'; import mainStyles from '~/common/styles/Main.style'; import scrollableTabViewStyles from '~/common/styles/ScrollableTabView.style'; diff --git a/src/selectors/alert.js b/src/modules/message/alert/alert.selectors.js similarity index 100% rename from src/selectors/alert.js rename to src/modules/message/alert/alert.selectors.js From 7bafb609973fea010de4db9660793ea9f44c10e2 Mon Sep 17 00:00:00 2001 From: just4fun Date: Fri, 31 Aug 2018 21:08:42 +0800 Subject: [PATCH 39/58] refactor: move modals to containers since they are stateful --- src/containers/ForumDetail/ForumDetail.js | 1 - .../ForumListModal/ForumListModal.js | 0 .../FriendListModal/FriendListModal.js | 0 .../LoginModal/LoginModal.js | 0 .../LoginModal/LoginModal.style.js | 0 src/containers/Menu/Menu.js | 1 - src/containers/Message/Message.js | 1 - src/containers/Navigator/Navigator.js | 10 +++++----- .../PublishModal/PublishModal.js | 0 .../PublishModal/PublishModal.style.js | 0 .../ReplyModal/ReplyModal.js | 2 +- .../ReplyModal/ReplyModal.style.js | 0 src/containers/TopicDetail/TopicDetail.js | 1 - 13 files changed, 6 insertions(+), 10 deletions(-) rename src/{components => containers}/ForumListModal/ForumListModal.js (100%) rename src/{components => containers}/FriendListModal/FriendListModal.js (100%) rename src/{components => containers}/LoginModal/LoginModal.js (100%) rename src/{components => containers}/LoginModal/LoginModal.style.js (100%) rename src/{components => containers}/PublishModal/PublishModal.js (100%) rename src/{components => containers}/PublishModal/PublishModal.style.js (100%) rename src/{components => containers}/ReplyModal/ReplyModal.js (99%) rename src/{components => containers}/ReplyModal/ReplyModal.style.js (100%) diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 217e2e1..59d039e 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -9,7 +9,6 @@ import _ from 'lodash'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import TopicList from '~/components/TopicList/TopicList'; import ForumItems from '~/components/ForumItems/ForumItems'; -import PublishModal from '~/components/PublishModal/PublishModal'; import PublishButton from '~/components/PublishButton/PublishButton'; import { invalidateTopicList, fetchTopicList, resetTopicList } from '~/modules/topic/topicList/topicList.ducks'; import { invalidateForumList, fetchForumList } from '~/modules/forum/forumList.ducks'; diff --git a/src/components/ForumListModal/ForumListModal.js b/src/containers/ForumListModal/ForumListModal.js similarity index 100% rename from src/components/ForumListModal/ForumListModal.js rename to src/containers/ForumListModal/ForumListModal.js diff --git a/src/components/FriendListModal/FriendListModal.js b/src/containers/FriendListModal/FriendListModal.js similarity index 100% rename from src/components/FriendListModal/FriendListModal.js rename to src/containers/FriendListModal/FriendListModal.js diff --git a/src/components/LoginModal/LoginModal.js b/src/containers/LoginModal/LoginModal.js similarity index 100% rename from src/components/LoginModal/LoginModal.js rename to src/containers/LoginModal/LoginModal.js diff --git a/src/components/LoginModal/LoginModal.style.js b/src/containers/LoginModal/LoginModal.style.js similarity index 100% rename from src/components/LoginModal/LoginModal.style.js rename to src/containers/LoginModal/LoginModal.style.js diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index 6f3af9c..9386fee 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -7,7 +7,6 @@ import { ActionSheetIOS, } from 'react-native'; import { SafeAreaView, NavigationActions } from 'react-navigation'; -import LoginModal from '~/components/LoginModal/LoginModal'; import MenuProfile from '~/components/MenuProfile/MenuProfile'; import MenuItem from '~/components/MenuItem/MenuItem'; import MenuBottomItem from '~/components/MenuBottomItem/MenuBottomItem'; diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index fe155da..467c43b 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -6,7 +6,6 @@ import ScrollableTabView from 'react-native-scrollable-tab-view'; import MessageTabBar from '~/common/vendor/components/MessageTabBar'; import NotifyList from '~/components/NotifyList/NotifyList'; import PmSessionList from '~/components/PmSessionList/PmSessionList'; -import ReplyModal from '~/components/ReplyModal/ReplyModal'; import MENUS from '~/constants/menus'; import { invalidateNotifyList, fetchNotifyList } from '~/modules/message/notifyList/notifyList.ducks'; import { invalidatePmSessionList, fetchPmSessionList, markPmAsRead } from '~/modules/message/pmSessionList/pmSessionList.ducks'; diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index c538b3f..c2c2617 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -16,11 +16,11 @@ import AboutScreen from '~/containers/About/About'; import InformationScreen from '~/containers/Information/Information'; import SettingsScreen from '~/containers/Settings/Settings'; import WebPageScreen from '~/containers/WebPage/WebPage'; -import LoginModalScreen from '~/components/LoginModal/LoginModal'; -import PublishModalScreen from '~/components/PublishModal/PublishModal'; -import ReplyModalScreen from '~/components/ReplyModal/ReplyModal'; -import ForumListModalScreen from '~/components/ForumListModal/ForumListModal'; -import FriendListModalScreen from '~/components/FriendListModal/FriendListModal'; +import LoginModalScreen from '~/containers/LoginModal/LoginModal'; +import PublishModalScreen from '~/containers/PublishModal/PublishModal'; +import ReplyModalScreen from '~/containers/ReplyModal/ReplyModal'; +import ForumListModalScreen from '~/containers/ForumListModal/ForumListModal'; +import FriendListModalScreen from '~/containers/FriendListModal/FriendListModal'; import { retrieveSessionFromStorage } from '~/modules/user/session/session.ducks'; import { retrieveSettingsFromStorage } from '~/modules/settings/settings.ducks'; import { fetchAlert } from '~/modules/message/alert/alert.ducks'; diff --git a/src/components/PublishModal/PublishModal.js b/src/containers/PublishModal/PublishModal.js similarity index 100% rename from src/components/PublishModal/PublishModal.js rename to src/containers/PublishModal/PublishModal.js diff --git a/src/components/PublishModal/PublishModal.style.js b/src/containers/PublishModal/PublishModal.style.js similarity index 100% rename from src/components/PublishModal/PublishModal.style.js rename to src/containers/PublishModal/PublishModal.style.js diff --git a/src/components/ReplyModal/ReplyModal.js b/src/containers/ReplyModal/ReplyModal.js similarity index 99% rename from src/components/ReplyModal/ReplyModal.js rename to src/containers/ReplyModal/ReplyModal.js index bc10e7d..c2fc461 100644 --- a/src/components/ReplyModal/ReplyModal.js +++ b/src/containers/ReplyModal/ReplyModal.js @@ -71,7 +71,7 @@ class ReplyModal extends Component { getTitle(comment) { if (comment) { return `回复 ${comment.user_nick_name || comment.reply_name}`; - } + } return '评论'; } diff --git a/src/components/ReplyModal/ReplyModal.style.js b/src/containers/ReplyModal/ReplyModal.style.js similarity index 100% rename from src/components/ReplyModal/ReplyModal.style.js rename to src/containers/ReplyModal/ReplyModal.style.js diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 38bebb8..f13c2c5 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -16,7 +16,6 @@ import _ from 'lodash'; import Icon from 'react-native-vector-icons/FontAwesome'; import { NavigationActions } from 'react-navigation'; import Avatar from '~/components/Avatar/Avatar'; -import ReplyModal from '~/components/ReplyModal/ReplyModal'; import Comment from '~/components/Comment/Comment'; import Content from '~/components/Content/Content'; import VoteList from '~/components/VoteList/VoteList'; From e37eb36b1d1234bcec3a77ff9b6b71c603abe638 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 9 Sep 2018 02:05:41 +0800 Subject: [PATCH 40/58] feat: set UIStatusBar to light per feedback --- ios/stuhome/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/stuhome/Info.plist b/ios/stuhome/Info.plist index cc6bddb..2898198 100644 --- a/ios/stuhome/Info.plist +++ b/ios/stuhome/Info.plist @@ -63,6 +63,8 @@ armv7 + UIStatusBarStyle + UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait From ab6a5499b1e358918588fbbb4104f7727578d46c Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 9 Sep 2018 16:42:32 +0800 Subject: [PATCH 41/58] fix: filter empty settings and session from storage --- src/modules/settings/settings.epics.js | 9 ++++----- src/modules/user/session/session.epics.js | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/modules/settings/settings.epics.js b/src/modules/settings/settings.epics.js index 007b7c5..f49c7ef 100644 --- a/src/modules/settings/settings.epics.js +++ b/src/modules/settings/settings.epics.js @@ -1,6 +1,6 @@ import { combineEpics, ofType } from 'redux-observable'; import { from as fromPromise, of, concat } from 'rxjs'; -import { mergeMap, map } from 'rxjs/operators'; +import { mergeMap, map, filter } from 'rxjs/operators'; import { AsyncStorage } from 'react-native'; import { SETTINGS_RETRIEVE, @@ -12,11 +12,10 @@ import api from '~/services/api'; const retrieveSettings = (action$) => action$.pipe( ofType(SETTINGS_RETRIEVE), mergeMap(action => fromPromise(AsyncStorage.getItem('settings')).pipe( + filter(settings => settings), map(settings => { - if (settings) { - settings = JSON.parse(settings); - return storeSettingsToRedux(settings); - } + settings = JSON.parse(settings); + return storeSettingsToRedux(settings); }) )) ); diff --git a/src/modules/user/session/session.epics.js b/src/modules/user/session/session.epics.js index ceb7f33..0592b96 100644 --- a/src/modules/user/session/session.epics.js +++ b/src/modules/user/session/session.epics.js @@ -1,6 +1,6 @@ import { combineEpics, ofType } from 'redux-observable'; import { from as fromPromise, of, concat } from 'rxjs'; -import { mergeMap, map } from 'rxjs/operators'; +import { mergeMap, map, filter } from 'rxjs/operators'; import { AsyncStorage } from 'react-native'; import { LOGIN, @@ -30,11 +30,10 @@ const login = (action$) => action$.pipe( const retrieveSession = (action$) => action$.pipe( ofType(SESSION_RETRIEVE), mergeMap(action => fromPromise(AsyncStorage.getItem('session')).pipe( + filter(session => session), map(session => { - if (session) { - session = JSON.parse(session); - return setSession(session); - } + session = JSON.parse(session); + return setSession(session); }) )) ); From ce2a36b1608b7411853093e089bae5383e92c0d7 Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 9 Sep 2018 17:40:38 +0800 Subject: [PATCH 42/58] refactor: expose `children` for right content of SettingItem --- src/components/SettingItem/SettingItem.js | 17 ++--- .../SettingItem/SettingItem.style.js | 17 ----- src/containers/About/About.style.js | 3 - src/containers/Information/Information.js | 63 +++++++++++++------ .../Information/Information.style.js | 25 ++++++++ src/containers/Search/Search.js | 1 - 6 files changed, 73 insertions(+), 53 deletions(-) create mode 100644 src/containers/Information/Information.style.js diff --git a/src/components/SettingItem/SettingItem.js b/src/components/SettingItem/SettingItem.js index e81be5f..ce94b4c 100644 --- a/src/components/SettingItem/SettingItem.js +++ b/src/components/SettingItem/SettingItem.js @@ -12,7 +12,7 @@ import styles from './SettingItem.style'; export default class SettingItem extends Component { render() { - let { text, style, indicator, avatar, isLoginUser } = this.props; + let { text, style, children } = this.props; return ( {text} - {!!avatar && - - - {isLoginUser && >} - - || - - {!!indicator ? indicator : '>'} - - } + {children || ( + > + )} ); diff --git a/src/components/SettingItem/SettingItem.style.js b/src/components/SettingItem/SettingItem.style.js index 46ffead..0049e06 100644 --- a/src/components/SettingItem/SettingItem.style.js +++ b/src/components/SettingItem/SettingItem.style.js @@ -18,22 +18,5 @@ export default StyleSheet.create({ flex: 1, textAlign: 'right', color: colors.underlay, - }, - avatarWapper: { - flex: 1, - flexDirection: 'row', - justifyContent: 'flex-end', - alignItems: 'center', - width: 50, - height: 50, - }, - avatar: { - width: 50, - height: 50, - borderRadius: 5, - }, - avatarIndicator: { - marginLeft: 10, - color: colors.underlay, } }); diff --git a/src/containers/About/About.style.js b/src/containers/About/About.style.js index 960ef3c..d856575 100644 --- a/src/containers/About/About.style.js +++ b/src/containers/About/About.style.js @@ -30,7 +30,4 @@ export default StyleSheet.create({ text: { color: colors.mainField, }, - informationAvatar: { - height: 60 - } }); diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index f9d5f6e..b569643 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -1,6 +1,10 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import { View } from 'react-native'; +import { + View, + Image, + Text +} from 'react-native'; import _ from 'lodash'; import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; @@ -16,8 +20,9 @@ import { } from '~/modules/user/user/user.ducks'; import mainStyles from '~/common/styles/Main.style'; -import indicatorStyles from '~/common/styles/Indicator.style'; -import styles from '~/containers/About/About.style'; +import aboutStyles from '~/containers/About/About.style'; +import settingItemStyles from '~/components/SettingItem/SettingItem.style'; +import styles from './Information.style'; class Information extends Component { static navigationOptions = { @@ -90,29 +95,49 @@ class Information extends Component { } return ( - - + + this.handleAvatarPress()} /> + style={styles.avatarItem} + onPress={() => this.handleAvatarPress()}> + + + {this.isLoginUser && >} + + + text='昵称'> + + {user.name} + + + text='性别'> + + {this.getGender(user.gender)} + + + text='等级'> + + {user.userTitle} + + + text='积分'> + + {user.credits} + + + text='水滴'> + + {user.gold_num} + + ); diff --git a/src/containers/Information/Information.style.js b/src/containers/Information/Information.style.js new file mode 100644 index 0000000..5cfe276 --- /dev/null +++ b/src/containers/Information/Information.style.js @@ -0,0 +1,25 @@ +import { StyleSheet } from 'react-native'; +import colors from '~/common/styles/colors.style'; + +export default StyleSheet.create({ + avatarItem: { + height: 60 + }, + avatarWapper: { + flex: 1, + flexDirection: 'row', + justifyContent: 'flex-end', + alignItems: 'center', + width: 50, + height: 50, + }, + avatar: { + width: 50, + height: 50, + borderRadius: 5, + }, + avatarIndicator: { + marginLeft: 10, + color: colors.underlay, + } +}); diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 638e805..0a68b68 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -16,7 +16,6 @@ import { } from '~/modules/topic/searchList/searchList.ducks'; import mainStyles from '~/common/styles/Main.style'; -import indicatorStyles from '~/common/styles/Indicator.style'; class Search extends Component { static navigationOptions = { From 453b325d33147586163c95b05993a90dcf26160d Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 9 Sep 2018 22:42:20 +0800 Subject: [PATCH 43/58] feat: font size setting --- src/constants/fontSize.js | 14 +++++ src/containers/Navigator/Navigator.js | 4 ++ src/containers/Settings/Settings.js | 14 ++++- .../SettingsFontSize/SettingsFontSize.js | 53 +++++++++++++++++++ .../SettingsFontSize.style.js | 11 ++++ src/modules/settings/settings.ducks.js | 3 +- 6 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/constants/fontSize.js create mode 100644 src/containers/SettingsFontSize/SettingsFontSize.js create mode 100644 src/containers/SettingsFontSize/SettingsFontSize.style.js diff --git a/src/constants/fontSize.js b/src/constants/fontSize.js new file mode 100644 index 0000000..5287693 --- /dev/null +++ b/src/constants/fontSize.js @@ -0,0 +1,14 @@ +export default [ + { + text: '大', + value: 'big' + }, + { + text: '中', + value: 'medium' + }, + { + text: '小', + value: 'small' + } +]; diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index c2c2617..fdd2fc2 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -15,6 +15,7 @@ import PrivateMessageScreen from '~/containers/PmList/PmList'; import AboutScreen from '~/containers/About/About'; import InformationScreen from '~/containers/Information/Information'; import SettingsScreen from '~/containers/Settings/Settings'; +import SettingsFontSizeScreen from '~/containers/SettingsFontSize/SettingsFontSize'; import WebPageScreen from '~/containers/WebPage/WebPage'; import LoginModalScreen from '~/containers/LoginModal/LoginModal'; import PublishModalScreen from '~/containers/PublishModal/PublishModal'; @@ -68,6 +69,9 @@ const AppNavigator = DrawerNavigator({ }, Settings: { screen: SettingsScreen + }, + SettingsFontSize: { + screen: SettingsFontSizeScreen } }, { initialRouteName: 'Home', diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index af38ea1..3ccdf5c 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -13,10 +13,12 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; import SettingSwitchItem from '~/components/SettingSwitchItem/SettingSwitchItem'; import MENUS from '~/constants/menus'; +import FONT_SIZES from '~/constants/fontSize'; import { storeSettingsToStorage } from '~/modules/settings/settings.ducks'; import { fetchAlert, resetAlert } from '~/modules/message/alert/alert.ducks'; import mainStyles from '~/common/styles/Main.style'; +import settingItemStyles from '~/components/SettingItem/SettingItem.style'; import styles from '~/containers/Settings/Settings.style'; class Settings extends Component { @@ -52,10 +54,20 @@ class Settings extends Component { } render() { - let { settings } = this.props; + let { settings, navigation } = this.props; + let fontSize = FONT_SIZES.find(item => item.value === settings.fontSize); return ( + + navigation.navigate('SettingsFontSize')}> + + {fontSize.text} > + + + { // // + + {FONT_SIZES.map((item, index) => ( + this.storeFontSize(item.value)}> + + {settings.fontSize === item.value && } + + + ))} + + + ); + } +} + +function mapStateToProps({ settings }) { + return { + settings + }; +} + +export default connect(mapStateToProps, { + storeSettingsToStorage +})(SettingsFontSize); diff --git a/src/containers/SettingsFontSize/SettingsFontSize.style.js b/src/containers/SettingsFontSize/SettingsFontSize.style.js new file mode 100644 index 0000000..8799155 --- /dev/null +++ b/src/containers/SettingsFontSize/SettingsFontSize.style.js @@ -0,0 +1,11 @@ +import { StyleSheet } from 'react-native'; +import colors from '~/common/styles/colors.style'; + +export default StyleSheet.create({ + container: { + backgroundColor: colors.background + }, + check: { + color: '#69d57a' + } +}); diff --git a/src/modules/settings/settings.ducks.js b/src/modules/settings/settings.ducks.js index ea0fef6..65a8c78 100644 --- a/src/modules/settings/settings.ducks.js +++ b/src/modules/settings/settings.ducks.js @@ -22,7 +22,8 @@ export const storeSettingsToRedux = createAction(SETTINGS_STORE_DONE); const defaultSettingsState = { enableNotification: true, - enablePublishDialog: false + enablePublishDialog: false, + fontSize: 'small' }; export default handleActions({ From df0eed25f913a83f5d184373fb82d4d03be8240f Mon Sep 17 00:00:00 2001 From: just4fun Date: Sun, 9 Sep 2018 23:32:56 +0800 Subject: [PATCH 44/58] feat: change topic content font size according to settings --- src/components/Comment/Comment.js | 4 ++- src/components/Content/Content.js | 9 ++++-- src/config.js | 4 ++- src/constants/fontSize.js | 12 +++++-- src/containers/Settings/Settings.js | 4 +-- .../SettingsFontSize/SettingsFontSize.js | 32 ++++++++++++++++++- .../SettingsFontSize.style.js | 11 +++++++ src/containers/TopicDetail/TopicDetail.js | 13 +++++--- 8 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/components/Comment/Comment.js b/src/components/Comment/Comment.js index f34f667..7eca7ba 100644 --- a/src/components/Comment/Comment.js +++ b/src/components/Comment/Comment.js @@ -108,7 +108,8 @@ export default class Comment extends Component { is_quote, quote_content, mobileSign - } + }, + settings } = this.props; posts_date = moment(+posts_date).startOf('minute').fromNow(); @@ -153,6 +154,7 @@ export default class Comment extends Component { } diff --git a/src/components/Content/Content.js b/src/components/Content/Content.js index 0ae933a..a9a0132 100644 --- a/src/components/Content/Content.js +++ b/src/components/Content/Content.js @@ -6,6 +6,7 @@ import { } from 'react-native'; import ProgressImage from '~/components/ProgressImage/ProgressImage'; import SafariView from '~/services/SafariView'; +import FONT_SIZES from '~/constants/fontSize'; import { parseContentWithEmoji } from '~/utils/contentParser'; import { DOMAIN_ROOT } from '~/config'; @@ -111,7 +112,8 @@ export default class Content extends Component { // adjust layout. render() { let newContent = this.getContentByGroup(); - let { navigation } = this.props; + let { navigation, settings } = this.props; + let selectedFontSize = FONT_SIZES.find(item => item.value === settings.fontSize); return ( @@ -127,7 +129,10 @@ export default class Content extends Component { case 4: return ( + style={[styles.item, styles.text, { + fontSize: selectedFontSize.fontSize, + lineHeight: selectedFontSize.lineHeight + }]}> {groupContent.map((item, index) => { return ( item.type === 0 && ( diff --git a/src/config.js b/src/config.js index 5726ebe..3bd3f25 100644 --- a/src/config.js +++ b/src/config.js @@ -25,6 +25,8 @@ module.exports = { AUTHOR_ID: 32044, + AUTHOR_NAME: '法律之光', + AUTHOR_URL: 'http://just4fun.github.io/', SOURCE_URL: 'https://github.com/just4fun/stuhome', @@ -33,7 +35,7 @@ module.exports = { APP_STORE: 'itms-apps://itunes.apple.com/cn/app/qing-shui-he-pan-stuhome/id1190564355', - COPY_RIGHT: `2015-${new Date().getFullYear()} 清水河畔@法律之光`, + COPY_RIGHT: `2015-${new Date().getFullYear()} 清水河畔`, // seconds ALERT_POLL_FREQUENCY: 15, diff --git a/src/constants/fontSize.js b/src/constants/fontSize.js index 5287693..09fdb99 100644 --- a/src/constants/fontSize.js +++ b/src/constants/fontSize.js @@ -1,14 +1,20 @@ export default [ { text: '大', - value: 'big' + value: 'big', + fontSize: 16, + lineHeight: 22 }, { text: '中', - value: 'medium' + value: 'medium', + fontSize: 15, + lineHeight: 20 }, { text: '小', - value: 'small' + value: 'small', + fontSize: 14, + lineHeight: 18 } ]; diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index 3ccdf5c..f70cb5d 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -55,7 +55,7 @@ class Settings extends Component { render() { let { settings, navigation } = this.props; - let fontSize = FONT_SIZES.find(item => item.value === settings.fontSize); + let selectedFontSize = FONT_SIZES.find(item => item.value === settings.fontSize); return ( @@ -64,7 +64,7 @@ class Settings extends Component { text='字体大小' onPress={() => navigation.navigate('SettingsFontSize')}> - {fontSize.text} > + {selectedFontSize.text} > diff --git a/src/containers/SettingsFontSize/SettingsFontSize.js b/src/containers/SettingsFontSize/SettingsFontSize.js index 89f2522..f752bf8 100644 --- a/src/containers/SettingsFontSize/SettingsFontSize.js +++ b/src/containers/SettingsFontSize/SettingsFontSize.js @@ -4,6 +4,7 @@ import { View, Text } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import SettingItem from '~/components/SettingItem/SettingItem'; import FONT_SIZES from '~/constants/fontSize'; +import * as configs from '~/config'; import { storeSettingsToStorage } from '~/modules/settings/settings.ducks'; import mainStyles from '~/common/styles/Main.style'; @@ -21,7 +22,18 @@ class SettingsFontSize extends Component { } render() { - let { settings } = this.props; + let { settings, navigation } = this.props; + let selectedFontSize = FONT_SIZES.find(item => item.value === settings.fontSize); + let authorLink = ( + navigation.navigate('Individual', { + userId: configs.AUTHOR_ID, + userName: configs.AUTHOR_NAME + })}> + {`@${configs.AUTHOR_NAME}`} + + ); return ( @@ -37,6 +49,24 @@ class SettingsFontSize extends Component { ))} + + + 这款 App 是由畔友 {authorLink} 利用业余时间,用编程语言 JavaScript 完成的。 + App 不仅一直保持开源,也一直坚持着代码结构的整洁与最新技术的引入。 + + + This App was created by {authorLink} in spare time with JavaScript. + The App is still keeping open source, while also keeping code structure + clean as well as introducing latest tech stack. + + ); } diff --git a/src/containers/SettingsFontSize/SettingsFontSize.style.js b/src/containers/SettingsFontSize/SettingsFontSize.style.js index 8799155..639ee75 100644 --- a/src/containers/SettingsFontSize/SettingsFontSize.style.js +++ b/src/containers/SettingsFontSize/SettingsFontSize.style.js @@ -7,5 +7,16 @@ export default StyleSheet.create({ }, check: { color: '#69d57a' + }, + demo: { + backgroundColor: colors.white, + borderBottomWidth: 0, + padding: 15 + }, + text: { + color: colors.mainField + }, + url: { + color: colors.link } }); diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index f13c2c5..82d9f4a 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -174,7 +174,8 @@ class TopicDetail extends Component { }, session: { data: { uid } - } + }, + settings } = this.props; let { isFavoring, isVoting } = this.state; let create_date = moment(+topic.create_date).startOf('minute').fromNow(); @@ -244,6 +245,7 @@ class TopicDetail extends Component { {topic.poll_info && Date: Wed, 12 Sep 2018 23:30:30 +0800 Subject: [PATCH 45/58] feat: reflect font size setting to each page --- src/components/Comment/Comment.js | 8 +++++- src/components/Content/Content.js | 11 ++++---- src/components/NotifyItem/NotifyItem.js | 13 ++++++--- src/components/NotifyList/NotifyList.js | 5 +++- .../NotifySystemItem/NotifySystemItem.js | 11 ++++++-- src/components/TopicItem/TopicItem.js | 25 ++++++++++------- src/components/TopicItem/TopicItem.style.js | 15 +++++++---- src/components/TopicList/TopicList.js | 4 ++- src/constants/fontSize.js | 23 +++++++--------- src/containers/ForumDetail/ForumDetail.js | 10 ++++--- src/containers/Home/Home.js | 9 ++++--- src/containers/Individual/Individual.js | 9 ++++--- src/containers/Message/Message.js | 9 ++++--- src/containers/Search/Search.js | 9 ++++--- src/containers/Settings/Settings.js | 20 +++++++------- .../SettingsFontSize/SettingsFontSize.js | 27 +++++++++---------- src/containers/TopicDetail/TopicDetail.js | 1 - 17 files changed, 128 insertions(+), 81 deletions(-) diff --git a/src/components/Comment/Comment.js b/src/components/Comment/Comment.js index 7eca7ba..cb4dd1a 100644 --- a/src/components/Comment/Comment.js +++ b/src/components/Comment/Comment.js @@ -12,6 +12,7 @@ import Content from '~/components/Content/Content'; import Avatar from '~/components/Avatar/Avatar'; import MessageBar from '~/services/MessageBar'; import SafariView from '~/services/SafariView'; +import FONT_SIZES from '~/constants/fontSize'; import colors from '~/common/styles/colors.style'; import styles from './Comment.style'; @@ -111,6 +112,11 @@ export default class Comment extends Component { }, settings } = this.props; + let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + let fontStyle = { + fontSize, + lineHeight + }; posts_date = moment(+posts_date).startOf('minute').fromNow(); @@ -149,7 +155,7 @@ export default class Comment extends Component { {!!is_quote && - {quote_content} + {quote_content} } item.value === settings.fontSize); + let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + let fontStyle = { + fontSize, + lineHeight + }; return ( @@ -129,10 +133,7 @@ export default class Content extends Component { case 4: return ( + style={[styles.item, styles.text, fontStyle]}> {groupContent.map((item, index) => { return ( item.type === 0 && ( diff --git a/src/components/NotifyItem/NotifyItem.js b/src/components/NotifyItem/NotifyItem.js index 0357bd2..d73e8e6 100644 --- a/src/components/NotifyItem/NotifyItem.js +++ b/src/components/NotifyItem/NotifyItem.js @@ -7,6 +7,7 @@ import { import Button from 'apsl-react-native-button'; import moment from 'moment'; import Avatar from '~/components/Avatar/Avatar'; +import FONT_SIZES from '~/constants/fontSize'; import colors from '~/common/styles/colors.style'; import styles from './NotifyItem.style'; @@ -27,10 +28,16 @@ export default class NotifyItem extends Component { reply_nick_name, reply_remind_id, replied_date - } + }, + settings } = this.props; replied_date = moment(+replied_date).startOf('minute').fromNow(); + let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + let fontStyle = { + fontSize, + lineHeight + }; return ( {replied_date} - {reply_content} + {reply_content} - {topic_content} + {topic_content} + board_name + })}> + + + + + {reply_nick_name} + {repliedDate} - - ); - } + {reply_content} + + {topic_content} + + + + + + + ); } diff --git a/src/components/NotifyList/NotifyList.js b/src/components/NotifyList/NotifyList.js index 22866f4..6f8276d 100644 --- a/src/components/NotifyList/NotifyList.js +++ b/src/components/NotifyList/NotifyList.js @@ -18,7 +18,7 @@ export default class NotifyList extends Component { } endReached() { - let { + const { hasMore, isRefreshing, isEndReached, @@ -35,7 +35,7 @@ export default class NotifyList extends Component { } renderFooter() { - let { + const { hasMore, isEndReached } = this.props.notifyList; @@ -60,15 +60,15 @@ export default class NotifyList extends Component { } render() { - let { + const { notifyList, navigation, currentUserId, refreshNotifyList, settings } = this.props; - let realNotifyList = []; let isRefreshing = false; + let realNotifyList = []; if (notifyList.list) { realNotifyList = notifyList.list; diff --git a/src/components/NotifySystemItem/NotifySystemItem.js b/src/components/NotifySystemItem/NotifySystemItem.js index 8d07ce8..383b3be 100644 --- a/src/components/NotifySystemItem/NotifySystemItem.js +++ b/src/components/NotifySystemItem/NotifySystemItem.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View, Text @@ -9,40 +9,37 @@ import FONT_SIZES from '~/constants/fontSize'; import styles from '~/components/NotifyItem/NotifyItem.style'; -export default class NotifyItem extends Component { - render() { - let { - notification: { - authorAvatar, - dateline, - note - }, - settings - } = this.props; +export default NotifyItem = (props) => { + const { + notification: { + authorAvatar, + dateline, + note + }, + settings + } = props; + const dateLine = moment(+dateline).startOf('minute').fromNow(); + const { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + const fontStyle = { + fontSize, + lineHeight + }; - dateline = moment(+dateline).startOf('minute').fromNow(); - let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; - let fontStyle = { - fontSize, - lineHeight - }; - - return ( - - - - - - {'系统'} - {dateline} - + return ( + + + + + + {'系统'} + {dateLine} - {note} + {note} - ); - } + + ); } diff --git a/src/components/Picker/Picker.js b/src/components/Picker/Picker.js index 9d7089e..19cb107 100644 --- a/src/components/Picker/Picker.js +++ b/src/components/Picker/Picker.js @@ -18,16 +18,14 @@ export default class Picker extends Component { } initId() { - let { list, selectedId } = this.props; + const { list, selectedId } = this.props; let id = selectedId; if (!id && (list && list.length)) { id = list[0].id; } - this.state = { - id - }; + this.state = { id }; } setSelection() { @@ -36,7 +34,7 @@ export default class Picker extends Component { } render() { - let { list } = this.props; + const { list } = this.props; return ( } {toUserName} - {lastDateline} + {date} {lastSummary} diff --git a/src/components/PmSessionList/PmSessionList.js b/src/components/PmSessionList/PmSessionList.js index 9c44f3d..1f1772e 100644 --- a/src/components/PmSessionList/PmSessionList.js +++ b/src/components/PmSessionList/PmSessionList.js @@ -17,7 +17,7 @@ export default class PrivateList extends Component { } endReached() { - let { + const { hasMore, isRefreshing, isEndReached, @@ -34,7 +34,7 @@ export default class PrivateList extends Component { } renderFooter() { - let { + const { hasMore, isEndReached } = this.props.pmSessionList; @@ -59,15 +59,15 @@ export default class PrivateList extends Component { } render() { - let { + const { pmSessionList, navigation, refreshPmSessionList, markPmAsRead, currentUserId } = this.props; - let realPmSessionList = []; let isRefreshing = false; + let realPmSessionList = []; if (pmSessionList.list) { realPmSessionList = pmSessionList.list; diff --git a/src/components/PopButton/PopButton.js b/src/components/PopButton/PopButton.js index be3de79..54909e6 100644 --- a/src/components/PopButton/PopButton.js +++ b/src/components/PopButton/PopButton.js @@ -1,17 +1,14 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -export default class PopButton extends Component { - render() { - let { action, style, navigation } = this.props; - - return ( - action ? action() : navigation.goBack()} /> - ); - } +export default PopButton = (props) => { + const { action, style, navigation } = props; + return ( + action ? action() : navigation.goBack()} /> + ); } diff --git a/src/components/ProgressImage/ProgressImage.js b/src/components/ProgressImage/ProgressImage.js index f89515a..5f8ed04 100644 --- a/src/components/ProgressImage/ProgressImage.js +++ b/src/components/ProgressImage/ProgressImage.js @@ -72,8 +72,8 @@ export default class ProgressImage extends Component { // } render() { - let { style, thumbUri, originalUri } = this.props; - let { isLoading, isLoadError } = this.state; + const { style, thumbUri, originalUri } = this.props; + const { isLoading, isLoadError } = this.state; return ( - ); - } +export default PublishButton = (props) => { + const { style, onPress } = props; + return ( + + ); } diff --git a/src/components/RewardList/RewardList.js b/src/components/RewardList/RewardList.js index 29f7b1c..774590f 100644 --- a/src/components/RewardList/RewardList.js +++ b/src/components/RewardList/RewardList.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View, Text, @@ -8,55 +8,50 @@ import Avatar from '~/components/Avatar/Avatar'; import styles from './RewardList.style'; -export default class RewardList extends Component { - render() { - let { - reward: { - score, - userNumber, - userList, - showAllUrl - }, - currentUserId, - navigation - } = this.props; +export default RewardList = (props) => { + const { + reward: { + score, + userNumber, + userList, + showAllUrl + }, + currentUserId, + navigation + } = props; - return ( - - - - {`共 ${userNumber} 人评分${score.map(({ info, value }) => { - if (value >= 0) { - value = `+${value}`; - } - - return `, ${info} ${value}`; - })}`} - - - - {userList.map((user, index) => { - return ( - - ); - })} - navigation.navigate('WebPage', { - url: showAllUrl, - title: '全部评分' - })} /> - + return ( + + + + {`共 ${userNumber} 人评分${score.map(({ info, value }) => { + if (value >= 0) { + value = `+${value}`; + } + return `, ${info} ${value}`; + })}`} + + + + {userList.map((user, index) => ( + + ))} + navigation.navigate('WebPage', { + url: showAllUrl, + title: '全部评分' + })} /> - ); - } + + ); } diff --git a/src/components/SettingItem/SettingItem.js b/src/components/SettingItem/SettingItem.js index ce94b4c..780d763 100644 --- a/src/components/SettingItem/SettingItem.js +++ b/src/components/SettingItem/SettingItem.js @@ -1,8 +1,7 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View, Text, - Image, TouchableHighlight } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; @@ -10,21 +9,18 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import colors from '~/common/styles/colors.style'; import styles from './SettingItem.style'; -export default class SettingItem extends Component { - render() { - let { text, style, children } = this.props; - - return ( - - - {text} - {children || ( - > - )} - - - ); - } +export default SettingItem = (props) => { + const { text, style, children, onPress } = props; + return ( + + + {text} + {children || ( + > + )} + + + ); } diff --git a/src/components/SettingSwitchItem/SettingSwitchItem.js b/src/components/SettingSwitchItem/SettingSwitchItem.js index 3849c74..6d01b09 100644 --- a/src/components/SettingSwitchItem/SettingSwitchItem.js +++ b/src/components/SettingSwitchItem/SettingSwitchItem.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View, Text, @@ -8,20 +8,17 @@ import { import mainStyles from '~/components/SettingItem/SettingItem.style'; import styles from './SettingSwitchItem.style'; -export default class SettingItem extends Component { - render() { - let { text, style, value, onValueChange } = this.props; - - return ( - - {text} - - - +export default SettingItem = (props) => { + const { text, style, value, onValueChange } = props; + return ( + + {text} + + - ); - } + + ); } diff --git a/src/components/SubForumItem/SubForumItem.js b/src/components/SubForumItem/SubForumItem.js index d8a9a06..c553512 100644 --- a/src/components/SubForumItem/SubForumItem.js +++ b/src/components/SubForumItem/SubForumItem.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View, Text, @@ -11,64 +11,61 @@ import FORUMS from '~/constants/forums'; import colors from '~/common/styles/colors.style'; import styles from './SubForumItem.style'; -export default class SubForumItem extends Component { - render() { - let { - navigation, - isForumListModal, - subForum, - subForum: { - board_id, - board_name, - td_posts_num, - posts_total_num, - topic_total_num, - last_posts_date - } - } = this.props; +export default SubForumItem = (props) => { + const { + navigation, + isForumListModal, + subForum, + subForum: { + board_id, + board_name, + td_posts_num, + posts_total_num, + topic_total_num, + last_posts_date + } + } = props; + const lastPostDate = moment(+last_posts_date).startOf('minute').fromNow(); + const boardImage = FORUMS[board_id] || require('~/images/board_img/default.png'); - let boardImage = FORUMS[board_id] || require('~/images/board_img/default.png'); - last_posts_date = moment(+last_posts_date).startOf('minute').fromNow(); - - return ( - { - if (isForumListModal) { - this.props.handleSelectForum(subForum); - } else { - navigation.navigate('Forum', subForum); - } - }}> - - - + return ( + { + if (isForumListModal) { + props.handleSelectForum(subForum); + } else { + navigation.navigate('Forum', subForum); + } + }}> + + + + + + + {board_name} + {lastPostDate} - - - {board_name} - {last_posts_date} + + + 主题: + {topic_total_num} + + + 贴子: + {posts_total_num} - - - 主题: - {topic_total_num} - - - 贴子: - {posts_total_num} - - - 今日: - {td_posts_num} - + + 今日: + {td_posts_num} - - ); - } + + + ); } diff --git a/src/components/SubForumList/SubForumList.js b/src/components/SubForumList/SubForumList.js index 506bd4c..1515877 100644 --- a/src/components/SubForumList/SubForumList.js +++ b/src/components/SubForumList/SubForumList.js @@ -1,22 +1,19 @@ -import React, { Component } from 'react'; +import React from 'react'; import { View } from 'react-native'; import SubForumItem from '~/components/SubForumItem/SubForumItem'; -export default class SubForumList extends Component { - render() { - let { forumList } = this.props; - - return ( - - {forumList.map(subForum => { - return ( - - ); - })} - - ); - } +export default SubForumList = (props) => { + const { forumList } = props; + return ( + + {forumList.map(subForum => { + return ( + + ); + })} + + ); } diff --git a/src/components/TopicItem/TopicItem.js b/src/components/TopicItem/TopicItem.js index 6e9e55a..1d1f916 100644 --- a/src/components/TopicItem/TopicItem.js +++ b/src/components/TopicItem/TopicItem.js @@ -17,7 +17,7 @@ import styles from './TopicItem.style'; export default class TopicItem extends Component { handleOnPress(topic) { - let { + const { currentUserId, navigation } = this.props; @@ -30,7 +30,7 @@ export default class TopicItem extends Component { } render() { - let { + const { navigation, settings, accessTopicListFromForumItem, @@ -50,17 +50,13 @@ export default class TopicItem extends Component { userAvatar } } = this.props; - - let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; - let fontStyle = { + // `last_reply_date` is timestamp in string from API + const lastReplyDate = moment(+last_reply_date).startOf('minute').fromNow(); + const { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + const fontStyle = { fontSize, lineHeight }; - // `last_reply_date` is timestamp in string from API - last_reply_date = moment(+last_reply_date).startOf('minute').fromNow(); - // for `Search`, there is no avatar available in API response, so we need to - // set it manually. - userAvatar = userAvatar || `${AVATAR_ROOT}&uid=${user_id}`; return ( @@ -72,7 +68,9 @@ export default class TopicItem extends Component { {user_nick_name} - {last_reply_date} + {lastReplyDate} {(!accessTopicListFromForumItem && !!board_name) && diff --git a/src/components/TopicList/TopicList.js b/src/components/TopicList/TopicList.js index 549ba71..a0a125c 100644 --- a/src/components/TopicList/TopicList.js +++ b/src/components/TopicList/TopicList.js @@ -31,7 +31,7 @@ export default class TopicList extends Component { } renderFooter() { - let { + const { hasMore, isEndReached } = this.props.topicList; @@ -73,7 +73,7 @@ export default class TopicList extends Component { } render() { - let { + const { topicList, isSearch, accessTopicListFromForumItem, @@ -91,13 +91,15 @@ export default class TopicList extends Component { }; if (!isSearch) { - refreshControl = this.props.refreshTopicList({ - page: 1, - isEndReached: false - })} - refreshing={isRefreshing} />; + refreshControl = ( + this.props.refreshTopicList({ + page: 1, + isEndReached: false + })} + refreshing={isRefreshing} /> + ) } return ( diff --git a/src/components/VoteList/VoteList.js b/src/components/VoteList/VoteList.js index eb58298..2976792 100644 --- a/src/components/VoteList/VoteList.js +++ b/src/components/VoteList/VoteList.js @@ -30,7 +30,7 @@ export default class VoteList extends Component { initState() { let pollListStatus = {}; - let { poll_item_list } = this.props.pollInfo; + const { poll_item_list } = this.props.pollInfo; poll_item_list.forEach(item => { pollListStatus[item.poll_item_id] = false; }); @@ -39,7 +39,7 @@ export default class VoteList extends Component { } setPollItemStatus(pollItemId, checked) { - let newPollListStatusState = Object.assign({}, this.state.pollListStatus, { + const newPollListStatusState = Object.assign({}, this.state.pollListStatus, { [pollItemId]: checked }); @@ -50,24 +50,23 @@ export default class VoteList extends Component { isSubmitDisabled() { // type: max selected items count (WTF???) - let { type } = this.props.pollInfo; - let { pollListStatus } = this.state; - let selectedItemsCount = Object.keys(pollListStatus).filter(key => pollListStatus[key]).length; + const { type } = this.props.pollInfo; + const { pollListStatus } = this.state; + const selectedItemsCount = Object.keys(pollListStatus).filter(key => pollListStatus[key]).length; return selectedItemsCount === 0 || (selectedItemsCount > type); } handleVote() { - let { pollListStatus } = this.state; - let voteIds = Object.keys(pollListStatus) + const { pollListStatus } = this.state; + const voteIds = Object.keys(pollListStatus) .filter(key => pollListStatus[key]) .join(','); - this.props.publishVote(voteIds); } render() { - let { + const { pollInfo: { poll_item_list, type, @@ -77,7 +76,7 @@ export default class VoteList extends Component { isVoting } = this.props; - let pollTitle = (type === 1 && '单选投票' || `多选投票(最多可选${type}项)`) + const pollTitle = (type === 1 && '单选投票' || `多选投票(最多可选${type}项)`) + (poll_status === 2 && ',投票后结果可见' || '') + `,共有${voters}人参与投票`; @@ -86,7 +85,7 @@ export default class VoteList extends Component { {pollTitle} {poll_item_list.map((item, index) => { - let percent = parseFloat(item.percent.substring(0, item.percent.length - 1)) / 100; + const percent = parseFloat(item.percent.substring(0, item.percent.length - 1)) / 100; let colorIndex = 0; if (index > 9) { @@ -95,8 +94,8 @@ export default class VoteList extends Component { colorIndex = index; } - let labelText = `${index + 1}. ${item.name}`; - let progressTintColor = progressTintColors[colorIndex]; + const labelText = `${index + 1}. ${item.name}`; + const progressTintColor = progressTintColors[colorIndex]; return ( diff --git a/src/containers/About/About.js b/src/containers/About/About.js index f091fcb..22e3272 100644 --- a/src/containers/About/About.js +++ b/src/containers/About/About.js @@ -23,7 +23,7 @@ export default class About extends Component { } render() { - let { navigation } = this.props; + const { navigation } = this.props; return ( diff --git a/src/containers/App/App.js b/src/containers/App/App.js index e11f26d..39ac0b8 100644 --- a/src/containers/App/App.js +++ b/src/containers/App/App.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import { Provider } from 'react-redux'; import configureStore from '~/store/configureStore'; import rootEpic from '~/modules/root/rootEpic'; @@ -7,12 +7,8 @@ import Navigator from '~/containers/Navigator/Navigator'; const store = configureStore(); store.runEpic(rootEpic); -export default class App extends Component { - render() { - return ( - - - - ); - } -} +export default App = () => ( + + + +) diff --git a/src/containers/ForumDetail/ForumDetail.js b/src/containers/ForumDetail/ForumDetail.js index 6a2730a..ea9b7d7 100644 --- a/src/containers/ForumDetail/ForumDetail.js +++ b/src/containers/ForumDetail/ForumDetail.js @@ -25,7 +25,7 @@ const TABS = [ class ForumDetail extends Component { static navigationOptions = ({ navigation }) => { - let { title, isLogin, boardId, handleModalCallback } = navigation.state.params; + const { title, isLogin, boardId, handleModalCallback } = navigation.state.params; return { title, headerRight: ( @@ -42,7 +42,7 @@ class ForumDetail extends Component { constructor(props) { super(props); - let { + const { board_id, board_name, board_content, @@ -55,7 +55,7 @@ class ForumDetail extends Component { } componentWillReceiveProps(nextProps) { - let errCode = _.get(nextProps, ['topicList', this.boardId, 'all', 'errCode'], ''); + const errCode = _.get(nextProps, ['topicList', this.boardId, 'all', 'errCode'], ''); if (errCode) { AlertIOS.alert('提示', errCode); // Clean error message. @@ -128,7 +128,7 @@ class ForumDetail extends Component { } render() { - let { + const { topicList, forumList, publish, diff --git a/src/containers/ForumList/ForumList.js b/src/containers/ForumList/ForumList.js index f129aa8..75d8bf6 100644 --- a/src/containers/ForumList/ForumList.js +++ b/src/containers/ForumList/ForumList.js @@ -40,7 +40,7 @@ class ForumList extends Component { } render() { - let { + const { navigation, forumList } = this.props; diff --git a/src/containers/ForumListModal/ForumListModal.js b/src/containers/ForumListModal/ForumListModal.js index b595246..6ad9c3c 100644 --- a/src/containers/ForumListModal/ForumListModal.js +++ b/src/containers/ForumListModal/ForumListModal.js @@ -37,14 +37,14 @@ class ForumListModal extends Component { } handleSelectForum(forum) { - let { navigation } = this.props; + const { navigation } = this.props; navigation.navigate('PublishModal', { boardId: forum.board_id }); } render() { - let { forumList, navigation } = this.props; + const { forumList, navigation } = this.props; return ( diff --git a/src/containers/FriendListModal/FriendListModal.js b/src/containers/FriendListModal/FriendListModal.js index 8a58d8e..dc34450 100644 --- a/src/containers/FriendListModal/FriendListModal.js +++ b/src/containers/FriendListModal/FriendListModal.js @@ -39,7 +39,7 @@ class FriendListModal extends Component { } render() { - let { friendList, navigation } = this.props; + const { friendList, navigation } = this.props; return ( diff --git a/src/containers/Home/Home.js b/src/containers/Home/Home.js index ed67fde..228535e 100644 --- a/src/containers/Home/Home.js +++ b/src/containers/Home/Home.js @@ -25,7 +25,7 @@ const TABS = [ class Home extends Component { static navigationOptions = ({ navigation }) => { - let { alertCount, isLogin } = _.get(navigation, ['state', 'params'], {}); + const { alertCount, isLogin } = _.get(navigation, ['state', 'params'], {}); return { title: '清水河畔', headerLeft: ( @@ -48,7 +48,7 @@ class Home extends Component { } componentDidMount() { - let { + const { userId, alertCount } = this.props; @@ -64,9 +64,9 @@ class Home extends Component { } componentWillReceiveProps(nextProps) { - let lastUserId = this.props.userId; - let lastAlertCount = this.props.alertCount; - let { + const lastUserId = this.props.userId; + const lastAlertCount = this.props.alertCount; + const { userId, alertCount } = nextProps; @@ -102,7 +102,7 @@ class Home extends Component { } render() { - let { + const { navigation, topicList, userId, diff --git a/src/containers/Individual/Individual.js b/src/containers/Individual/Individual.js index 3bb43c9..27c2b11 100644 --- a/src/containers/Individual/Individual.js +++ b/src/containers/Individual/Individual.js @@ -23,7 +23,7 @@ import styles from './Individual.style'; class Individual extends Component { static navigationOptions = ({ navigation }) => { - let { userId, isLoginUser } = _.get(navigation, ['state', 'params'], {}); + const { userId, isLoginUser } = _.get(navigation, ['state', 'params'], {}); return { headerStyle: { backgroundColor: colors.lightBlue, @@ -48,7 +48,7 @@ class Individual extends Component { initTabsAndUserInformation() { this.TABS = []; - let { + const { session, navigation: { state: { @@ -59,7 +59,7 @@ class Individual extends Component { this.isLoginUser = !passProps || (+passProps.userId === session.data.uid); if (this.isLoginUser) { - let { + const { session: { data: { uid, @@ -78,7 +78,7 @@ class Individual extends Component { { label: '我的收藏', type: 'favorite' } ]; } else { - let { + const { userId, userName, userAvatar @@ -130,7 +130,7 @@ class Individual extends Component { } render() { - let { + const { navigation, userTopicList, settings diff --git a/src/containers/Information/Information.js b/src/containers/Information/Information.js index ddb8e62..ee8dd76 100644 --- a/src/containers/Information/Information.js +++ b/src/containers/Information/Information.js @@ -34,7 +34,7 @@ class Information extends Component { super(props); this.userId = this.props.navigation.state.params.userId; - let { loginUserId } = this.props; + const { loginUserId } = this.props; this.isLoginUser = loginUserId === this.userId; } @@ -76,7 +76,7 @@ class Information extends Component { handleAvatarPress() { if (!this.isLoginUser) { return; } - let photoOptions = { + const photoOptions = { width: 500, height: 500, cropping: true @@ -97,7 +97,7 @@ class Information extends Component { } render() { - let { + const { userItem: { isFetching, user diff --git a/src/containers/LoginModal/LoginModal.js b/src/containers/LoginModal/LoginModal.js index fe14e95..0e9aa7b 100644 --- a/src/containers/LoginModal/LoginModal.js +++ b/src/containers/LoginModal/LoginModal.js @@ -45,7 +45,7 @@ class LoginModal extends Component { } componentWillReceiveProps(nextProps) { - let { isFetching, data, hasError, result } = nextProps.session; + const { isFetching, data, hasError, result } = nextProps.session; if (hasError) { AlertIOS.alert('提示', data.errcode); @@ -54,8 +54,8 @@ class LoginModal extends Component { if (result) { this.props.resetSessionResult(); - data = JSON.stringify(data); - AsyncStorage.setItem('session', data) + const json = JSON.stringify(data); + AsyncStorage.setItem('session', json) .then(() => { // Remove all cache except session. this.props.logout({ isLogin: true }); @@ -84,14 +84,14 @@ class LoginModal extends Component { } render() { - let { + const { session: { isFetching }, navigation } = this.props; - let { userName, password } = this.state; - let isDisabled = !userName || !password || isFetching; + const { userName, password } = this.state; + const isDisabled = !userName || !password || isFetching; return ( diff --git a/src/containers/Menu/Menu.js b/src/containers/Menu/Menu.js index 9386fee..29f1eca 100644 --- a/src/containers/Menu/Menu.js +++ b/src/containers/Menu/Menu.js @@ -59,7 +59,7 @@ class Menu extends Component { } render() { - let { + const { session: { data, data: { token } diff --git a/src/containers/Message/Message.js b/src/containers/Message/Message.js index bb942e9..e3e443e 100644 --- a/src/containers/Message/Message.js +++ b/src/containers/Message/Message.js @@ -63,7 +63,7 @@ class Message extends Component { // for each tab of component. getTabsWithAlertCount(tabs) { let newTabs = []; - let { atMeCount, replyCount, pmCount, systemCount } = this.props; + const { atMeCount, replyCount, pmCount, systemCount } = this.props; newTabs.push({ name: tabs[0], count: atMeCount }); newTabs.push({ name: tabs[1], count: replyCount }); newTabs.push({ name: tabs[2], count: pmCount }); @@ -72,7 +72,7 @@ class Message extends Component { } render() { - let { + const { notifyList, pmSessionList, reply, diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index 552a063..c008127 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -140,11 +140,11 @@ class AppRoot extends Component { } componentWillReceiveProps(nextProps) { - let currentToken = this.props.session.data.token; - let nextToken = nextProps.session.data.token; + const currentToken = this.props.session.data.token; + const nextToken = nextProps.session.data.token; - let currentEnableNotification = this.props.settings.enableNotification; - let nextEnableNotification = nextProps.settings.enableNotification; + const currentEnableNotification = this.props.settings.enableNotification; + const nextEnableNotification = nextProps.settings.enableNotification; if (currentToken === nextToken && currentEnableNotification === nextEnableNotification) { return; } diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index 31eaea7..85d33c2 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -28,7 +28,7 @@ const LOGIN_USER_ID = Symbol(); class PmList extends Component { static navigationOptions = ({ navigation }) => { - let { title } = navigation.state.params; + const { title } = navigation.state.params; return { title }; @@ -37,7 +37,7 @@ class PmList extends Component { constructor(props) { super(props); - let { userId } = this.props.navigation.state.params; + const { userId } = this.props.navigation.state.params; this.userId = userId; this.state = { messages: [], @@ -66,18 +66,18 @@ class PmList extends Component { } setUpTitle(newUserName) { - let userName = this.props.pmList.user.name; + const userName = this.props.pmList.user.name; if (userName !== newUserName) { this.props.navigation.setParams({ title: newUserName }); } } componentWillReceiveProps(nextProps) { - let { pmList } = nextProps; + const { pmList } = nextProps; this.setUpTitle(pmList.user.name); // Handle private messages. - let { isPublishing } = this.state; + const { isPublishing } = this.state; if (isPublishing) { return; } @@ -121,7 +121,7 @@ class PmList extends Component { return; } - let { rs, errcode } = response.data; + const { rs, errcode } = response.data; if (rs) { // This is workaround to fix #14. // In produciton, sometimes the new sent message can not be displayed @@ -143,7 +143,7 @@ class PmList extends Component { } render() { - let { + const { navigation, pmList: { isRefreshing, @@ -152,7 +152,7 @@ class PmList extends Component { page } } = this.props; - let { isPublishing } = this.state; + const { isPublishing } = this.state; if (isRefreshing && page === 0) { return ( @@ -160,7 +160,7 @@ class PmList extends Component { ); } - let messages = this.state.messages.map(item => { + const messages = this.state.messages.map(item => { if (item.isNew) { return item; } return { diff --git a/src/containers/PublishModal/PublishModal.js b/src/containers/PublishModal/PublishModal.js index 92e580b..841a28b 100644 --- a/src/containers/PublishModal/PublishModal.js +++ b/src/containers/PublishModal/PublishModal.js @@ -75,7 +75,7 @@ class PublishModal extends Component { } handleCancel() { - let { title, content, images } = this.state; + const { title, content, images } = this.state; if (title.length || content.length || images.length) { AlertIOS.alert( '提示', @@ -94,11 +94,11 @@ class PublishModal extends Component { } isFormValid() { - let { typeId, title, content } = this.state; - let { types } = this.props; + const { typeId, title, content } = this.state; + const { types } = this.props; - let hasNoTopicTypes = types.length === 0; - let hasTypeId = hasNoTopicTypes && true || (typeId !== null); + const hasNoTopicTypes = types.length === 0; + const hasTypeId = hasNoTopicTypes && true || (typeId !== null); return hasTypeId && title.length @@ -130,7 +130,7 @@ class PublishModal extends Component { // this.setState({ isPublishing: true }); this.modalLoadingSpinnerOverLay.show(); api.uploadImages(this.state.images).then(data => { - let { typeId, title, content } = this.state; + const { typeId, title, content } = this.state; return api.publishTopic({ boardId: this.boardId, // topicId: null, @@ -181,7 +181,7 @@ class PublishModal extends Component { if (this.state.isPublishing) { return; } this.setState((prevState) => { - let newContent = prevState.content.substr(0, this.contentCursorLocation) + const newContent = prevState.content.substr(0, this.contentCursorLocation) + extraContent + prevState.content.substr(this.contentCursorLocation); return { content: newContent }; @@ -232,7 +232,7 @@ class PublishModal extends Component { } hideKeyboard() { - let { selectedPanel } = this.state; + const { selectedPanel } = this.state; if (selectedPanel === 'keyboard') { Keyboard.dismiss(); @@ -257,7 +257,7 @@ class PublishModal extends Component { } render() { - let { + const { typeId, content, isPickerOpen, @@ -266,7 +266,7 @@ class PublishModal extends Component { selectedPanel, isTitleFocused } = this.state; - let { types } = this.props; + const { types } = this.props; return ( diff --git a/src/containers/ReplyModal/ReplyModal.js b/src/containers/ReplyModal/ReplyModal.js index c2fc461..f38b930 100644 --- a/src/containers/ReplyModal/ReplyModal.js +++ b/src/containers/ReplyModal/ReplyModal.js @@ -40,7 +40,7 @@ class ReplyModal extends Component { } initNecessaryData() { - let { + const { comment, comment: { reply_posts_id, @@ -81,7 +81,7 @@ class ReplyModal extends Component { } handleCancel() { - let { replyContent, images } = this.state; + const { replyContent, images } = this.state; if (replyContent.length || images.length) { AlertIOS.alert( '提示', @@ -188,7 +188,7 @@ class ReplyModal extends Component { if (this.state.isPublishing) { return; } this.setState((prevState) => { - let newContent = prevState.replyContent.substr(0, this.contentCursorLocation) + const newContent = prevState.replyContent.substr(0, this.contentCursorLocation) + extraContent + prevState.replyContent.substr(this.contentCursorLocation); return { replyContent: newContent }; @@ -211,7 +211,7 @@ class ReplyModal extends Component { } hideKeyboard() { - let { selectedPanel } = this.state; + const { selectedPanel } = this.state; if (selectedPanel === 'keyboard') { Keyboard.dismiss(); @@ -236,7 +236,7 @@ class ReplyModal extends Component { } render() { - let { + const { replyContent, isPublishing, selectedPanel, diff --git a/src/containers/Search/Search.js b/src/containers/Search/Search.js index 54c1a5a..3ad9bc1 100644 --- a/src/containers/Search/Search.js +++ b/src/containers/Search/Search.js @@ -41,7 +41,7 @@ class Search extends Component { } componentWillReceiveProps(nextProps) { - let { searchList } = nextProps; + const { searchList } = nextProps; if (searchList.errCode) { AlertIOS.alert('提示', searchList.errCode); // Clean error message. @@ -79,7 +79,7 @@ class Search extends Component { } render() { - let { + const { navigation, searchList, userId, diff --git a/src/containers/Settings/Settings.js b/src/containers/Settings/Settings.js index c754fb5..cc43a5a 100644 --- a/src/containers/Settings/Settings.js +++ b/src/containers/Settings/Settings.js @@ -54,8 +54,8 @@ class Settings extends Component { } render() { - let { settings, navigation } = this.props; - let selectedFontSize = FONT_SIZES[settings.fontSize]; + const { settings, navigation } = this.props; + const selectedFontSize = FONT_SIZES[settings.fontSize]; return ( diff --git a/src/containers/SettingsFontSize/SettingsFontSize.js b/src/containers/SettingsFontSize/SettingsFontSize.js index b37aea9..f9cd4e9 100644 --- a/src/containers/SettingsFontSize/SettingsFontSize.js +++ b/src/containers/SettingsFontSize/SettingsFontSize.js @@ -22,13 +22,13 @@ class SettingsFontSize extends Component { } render() { - let { settings, navigation } = this.props; - let { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; - let fontStyle = { + const { settings, navigation } = this.props; + const { fontSize, lineHeight } = FONT_SIZES[settings.fontSize]; + const fontStyle = { fontSize, lineHeight }; - let authorLink = ( + const authorLink = ( navigation.navigate('Individual', { diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 5b8370d..3f1ad13 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -55,7 +55,7 @@ function getTopicId(topic) { class TopicDetail extends Component { static navigationOptions = ({ navigation }) => { - let { headerTitle, isLogin, handleShowOperationDialog } = navigation.state.params; + const { headerTitle, isLogin, handleShowOperationDialog } = navigation.state.params; return { title: headerTitle, headerRight: ( @@ -72,7 +72,7 @@ class TopicDetail extends Component { constructor(props) { super(props); - let { params } = props.navigation.state; + const { params } = props.navigation.state; this.topicId = getTopicId(params); this.boardId = params.board_id; this.boardName = params.board_name; @@ -102,7 +102,7 @@ class TopicDetail extends Component { } componentWillReceiveProps(nextProps) { - let { topicItem } = nextProps; + const { topicItem } = nextProps; // Seems like the code here won't be invoked since we // display login modal instead when user clicks topic in @@ -150,7 +150,7 @@ class TopicDetail extends Component { } endReached() { - let { + const { hasMore, isFetching, isEndReached, @@ -166,7 +166,7 @@ class TopicDetail extends Component { } renderHeader() { - let { + const { navigation, vote, topicItem: { @@ -177,9 +177,9 @@ class TopicDetail extends Component { }, settings } = this.props; - let { isFavoring, isVoting } = this.state; - let create_date = moment(+topic.create_date).startOf('minute').fromNow(); - let commentHeaderText = + const { isFavoring, isVoting } = this.state; + const create_date = moment(+topic.create_date).startOf('minute').fromNow(); + const commentHeaderText = topic.replies > 0 ? (topic.replies + '条评论') : '还没有评论,快来抢沙发!'; // Same with f227938f. if (topic.user_id === 0) { @@ -269,7 +269,7 @@ class TopicDetail extends Component { } renderFooter() { - let { + const { hasMore, isEndReached } = this.props.topicItem; @@ -324,7 +324,7 @@ class TopicDetail extends Component { '复制内容', '复制链接' ]; - let { + const { session: { data: { uid } }, @@ -335,8 +335,8 @@ class TopicDetail extends Component { } } } = this.props; - let isLoginUser = uid === user_id; - let editable = + const isLoginUser = uid === user_id; + const editable = isLoginUser && managePanel && managePanel.length > 0 && !!managePanel.find(item => item.title === '编辑'); if (editable) { options.push('编辑帖子'); @@ -348,7 +348,7 @@ class TopicDetail extends Component { cancelButtonIndex: options.length - 1 }, (buttonIndex) => { - let { topic } = this.props.topicItem; + const { topic } = this.props.topicItem; switch (buttonIndex) { case 0: this.props.navigation.dispatch(resetAction); @@ -377,7 +377,7 @@ class TopicDetail extends Component { break; case 5: if (editable) { - let editAction = managePanel.find(item => item.title === '编辑'); + const editAction = managePanel.find(item => item.title === '编辑'); SafariView.show(editAction.action); } break; @@ -386,7 +386,7 @@ class TopicDetail extends Component { } render() { - let { topicItem } = this.props; + const { topicItem } = this.props; if (topicItem.isFetching || !_.get(topicItem, ['topic', 'topic_id'])) { return ( @@ -394,7 +394,7 @@ class TopicDetail extends Component { ); } - let { + const { topicItem: { topic: { user_nick_name, @@ -463,7 +463,7 @@ class TopicDetail extends Component { } function mapStateToProps(state, ownProps) { - let { topicItem, session, settings } = state; + const { topicItem, session, settings } = state; return { topicItem: _.get(topicItem, getTopicId(ownProps.navigation.state.params), {}), diff --git a/src/containers/WebPage/WebPage.js b/src/containers/WebPage/WebPage.js index 7673dbe..680f7d2 100644 --- a/src/containers/WebPage/WebPage.js +++ b/src/containers/WebPage/WebPage.js @@ -3,14 +3,14 @@ import { WebView } from 'react-native'; export default class WebPage extends Component { static navigationOptions = ({ navigation }) => { - let { title } = navigation.state.params; + const { title } = navigation.state.params; return { title }; } render() { - let { + const { url, title, navigation, From 755a89ce832181f25d4519bd016ea5c07343c800 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 17 Sep 2018 23:10:40 +0800 Subject: [PATCH 54/58] refactor: remove WebPage component --- src/components/RewardList/RewardList.js | 6 ++--- src/containers/Navigator/Navigator.js | 4 ---- src/containers/WebPage/WebPage.js | 32 ------------------------- 3 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 src/containers/WebPage/WebPage.js diff --git a/src/components/RewardList/RewardList.js b/src/components/RewardList/RewardList.js index 774590f..32fbc3b 100644 --- a/src/components/RewardList/RewardList.js +++ b/src/components/RewardList/RewardList.js @@ -5,6 +5,7 @@ import { } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import Avatar from '~/components/Avatar/Avatar'; +import SafariView from '~/services/SafariView'; import styles from './RewardList.style'; @@ -47,10 +48,7 @@ export default RewardList = (props) => { style={[styles.rewardUser, styles.more]} name='ellipsis-h' size={14} - onPress={() => navigation.navigate('WebPage', { - url: showAllUrl, - title: '全部评分' - })} /> + onPress={() => SafariView.show(showAllUrl)} /> ); diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index c008127..20f6b10 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -16,7 +16,6 @@ import AboutScreen from '~/containers/About/About'; import InformationScreen from '~/containers/Information/Information'; import SettingsScreen from '~/containers/Settings/Settings'; import SettingsFontSizeScreen from '~/containers/SettingsFontSize/SettingsFontSize'; -import WebPageScreen from '~/containers/WebPage/WebPage'; import LoginModalScreen from '~/containers/LoginModal/LoginModal'; import PublishModalScreen from '~/containers/PublishModal/PublishModal'; import ReplyModalScreen from '~/containers/ReplyModal/ReplyModal'; @@ -58,9 +57,6 @@ const AppNavigator = DrawerNavigator({ PrivateMessage: { screen: PrivateMessageScreen }, - WebPage: { - screen: WebPageScreen - }, About: { screen: AboutScreen }, diff --git a/src/containers/WebPage/WebPage.js b/src/containers/WebPage/WebPage.js deleted file mode 100644 index 680f7d2..0000000 --- a/src/containers/WebPage/WebPage.js +++ /dev/null @@ -1,32 +0,0 @@ -import React, { Component } from 'react'; -import { WebView } from 'react-native'; - -export default class WebPage extends Component { - static navigationOptions = ({ navigation }) => { - const { title } = navigation.state.params; - return { - title - }; - } - - render() { - const { - url, - title, - navigation, - navigation: { - state: { - params - } - } - } = this.props; - - return ( - - ); - } -} From 86ddb3aa31a03a11a0fa9f0d9bb9d1c416eb3720 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 17 Sep 2018 23:17:45 +0800 Subject: [PATCH 55/58] refactor: replace !!arr.find with arr.some --- src/components/Comment/Comment.js | 13 ++++++++----- src/containers/TopicDetail/TopicDetail.js | 22 +++++++++++++--------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/components/Comment/Comment.js b/src/components/Comment/Comment.js index dadae2c..5754309 100644 --- a/src/components/Comment/Comment.js +++ b/src/components/Comment/Comment.js @@ -32,15 +32,18 @@ export default class Comment extends Component { } } = this.props; + const isLoginUser = currentUserId === userId; + // If userId is 0, it's anonymous user. + const canSendPrivateMessage = !isLoginUser && userId !== 0; + const editable = isLoginUser + && managePanel + && managePanel.length > 0 + && managePanel.some(item => item.title === '编辑'); + let options = [ '回复', '复制' ]; - const isLoginUser = currentUserId === userId; - // If userId is 0, it's anonymous user. - const canSendPrivateMessage = !isLoginUser && userId !== 0; - const editable = - isLoginUser && managePanel && managePanel.length > 0 && !!managePanel.find(item => item.title === '编辑'); if (canSendPrivateMessage) { options.push('私信'); } else if (editable) { diff --git a/src/containers/TopicDetail/TopicDetail.js b/src/containers/TopicDetail/TopicDetail.js index 3f1ad13..c1f1afe 100644 --- a/src/containers/TopicDetail/TopicDetail.js +++ b/src/containers/TopicDetail/TopicDetail.js @@ -317,13 +317,6 @@ class TopicDetail extends Component { showOperationDialog() { if (this.props.topicItem.isFetching) { return; } - let options = [ - '返回首页', - this.order === 0 ? '倒序查看' : '顺序查看', - this.authorId === 0 ? '只看楼主' : '查看全部', - '复制内容', - '复制链接' - ]; const { session: { data: { uid } @@ -335,9 +328,20 @@ class TopicDetail extends Component { } } } = this.props; + const isLoginUser = uid === user_id; - const editable = - isLoginUser && managePanel && managePanel.length > 0 && !!managePanel.find(item => item.title === '编辑'); + const editable = isLoginUser + && managePanel + && managePanel.length > 0 + && managePanel.some(item => item.title === '编辑'); + + let options = [ + '返回首页', + this.order === 0 ? '倒序查看' : '顺序查看', + this.authorId === 0 ? '只看楼主' : '查看全部', + '复制内容', + '复制链接' + ]; if (editable) { options.push('编辑帖子'); } From 2abdfe1644f272005cff9873b240cc2820ed0918 Mon Sep 17 00:00:00 2001 From: just4fun Date: Mon, 17 Sep 2018 23:30:10 +0800 Subject: [PATCH 56/58] refactor: remove Symbol --- index.js | 3 --- package.json | 1 - src/containers/PmList/PmList.js | 6 +++--- yarn.lock | 33 --------------------------------- 4 files changed, 3 insertions(+), 40 deletions(-) diff --git a/index.js b/index.js index d9f4cce..21d46d0 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,3 @@ -// make `Symbol` available on iOS 8 -import 'es6-symbol/implement'; - import { AppRegistry } from 'react-native'; import App from '~/containers/App/App'; diff --git a/package.json b/package.json index a05b89f..0df24db 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ }, "dependencies": { "apsl-react-native-button": "3.1.0", - "es6-symbol": "3.1.1", "lodash": "4.17.4", "md5": "2.1.0", "moment": "2.19.3", diff --git a/src/containers/PmList/PmList.js b/src/containers/PmList/PmList.js index 85d33c2..720bd51 100644 --- a/src/containers/PmList/PmList.js +++ b/src/containers/PmList/PmList.js @@ -24,7 +24,7 @@ import api from '~/services/api'; import mainStyles from '~/common/styles/Main.style'; import styles from './PmList.style'; -const LOGIN_USER_ID = Symbol(); +const __CURRENT_LOGIN_USER_ID__ = '__CURRENT_LOGIN_USER_ID__'; class PmList extends Component { static navigationOptions = ({ navigation }) => { @@ -168,7 +168,7 @@ class PmList extends Component { text: item.content, createdAt: new Date(+item.time), user: { - _id: (item.sender === user.id) && item.sender || LOGIN_USER_ID, + _id: (item.sender === user.id) && item.sender || __CURRENT_LOGIN_USER_ID__, avatar: (item.sender === user.id) && user.avatar } }; @@ -203,7 +203,7 @@ class PmList extends Component { ); }} messages={messages} - user={{ _id: LOGIN_USER_ID }} /> + user={{ _id: __CURRENT_LOGIN_USER_ID__ }} /> ); } diff --git a/yarn.lock b/yarn.lock index 7c02dfe..d16698c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1460,12 +1460,6 @@ cubic-bezier@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/cubic-bezier/-/cubic-bezier-0.1.2.tgz#d4970942002e45372e0aa92db657e39eaf6824d7" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1725,29 +1719,6 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.45" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.45.tgz#0bfdf7b473da5919d5adf3bd25ceb754fccc3653" - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - escape-html@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" @@ -3299,10 +3270,6 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - nice-try@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" From bb04f6d7213418a99322f69097250f13fc11905a Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 18 Sep 2018 13:38:00 +0800 Subject: [PATCH 57/58] fix: set status bar to dark style once in-app Safari opened --- src/containers/Navigator/Navigator.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/containers/Navigator/Navigator.js b/src/containers/Navigator/Navigator.js index 20f6b10..4264f51 100644 --- a/src/containers/Navigator/Navigator.js +++ b/src/containers/Navigator/Navigator.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import { View, ScrollView } from 'react-native'; +import { StatusBar } from 'react-native'; import { DrawerNavigator, StackNavigator, SafeAreaView } from 'react-navigation'; import { MessageBar, MessageBarManager } from 'react-native-message-bar'; +import SafariView from 'react-native-safari-view'; import Menu from '~/containers/Menu/Menu'; import HomeScreen from '~/containers/Home/Home'; import ForumListScreen from '~/containers/ForumList/ForumList'; @@ -133,6 +134,26 @@ class AppRoot extends Component { this.props.retrieveSessionFromStorage(); this.props.retrieveSettingsFromStorage(); + + this.addEventListenersToSafariView(); + } + + setStatusBarToDarkStyle() { + StatusBar.setBarStyle('dark-content'); + } + + setStatusBarToLightStyle() { + StatusBar.setBarStyle('light-content'); + } + + addEventListenersToSafariView() { + SafariView.addEventListener('onShow', this.setStatusBarToDarkStyle); + SafariView.addEventListener('onDismiss', this.setStatusBarToLightStyle); + } + + removeEventListenersFromSafariView() { + SafariView.removeEventListener('onShow', this.setStatusBarToDarkStyle); + SafariView.removeEventListener('onDismiss', this.setStatusBarToLightStyle); } componentWillReceiveProps(nextProps) { @@ -164,6 +185,7 @@ class AppRoot extends Component { componentWillUnmount() { MessageBarManager.unregisterMessageBar(); this.timer && clearInterval(this.timer); + this.removeEventListenersFromSafariView(); } render() { From 310208361a067b04b0eadfa07b7fdc8c581f10fd Mon Sep 17 00:00:00 2001 From: just4fun Date: Tue, 18 Sep 2018 21:34:50 +0800 Subject: [PATCH 58/58] docs: make README.md concise --- README.md | 34 +++++++++++++--------------------- package.json | 2 +- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 56d4831..99d3b69 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,11 @@ [![GitHub issues](https://img.shields.io/github/issues/just4fun/stuhome.svg)](https://github.com/just4fun/stuhome/issues) [![MIT](https://img.shields.io/dub/l/vibe-d.svg)](http://opensource.org/licenses/MIT) -An officially recommended iOS client for http://bbs.uestc.edu.cn/ written in [React Native](https://facebook.github.io/react-native/) with [Redux](http://redux.js.org/). APIs are provided by [UESTC-BBS/API-Docs](https://github.com/UESTC-BBS/API-Docs/wiki/Mobcent-API) and [appbyme/mobcent-discuz](https://github.com/appbyme/mobcent-discuz). +An officially recommended 3rd party iOS client for http://bbs.uestc.edu.cn/ written in [react-native](https://facebook.github.io/react-native/), [redux](http://redux.js.org/) and [redux-observable](https://redux-observable.js.org/). -For all officially recommended clients, please visit http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1554255. - -## Old logo (from v1.0.0 to v1.3.0) +APIs are provided by [appbyme/mobcent-discuz](https://github.com/appbyme/mobcent-discuz) and partly documented by [UESTC-BBS/API-Docs](https://github.com/UESTC-BBS/API-Docs/wiki/Mobcent-API). -![app_icon](https://cloud.githubusercontent.com/assets/7512625/18613513/348f7322-7daf-11e6-902d-94776bb55670.jpg) +For all officially recommended clients, please visit http://bbs.uestc.edu.cn/forum.php?mod=viewthread&tid=1554255. ## Status (v1.7.0) @@ -22,7 +20,7 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for ![stuhome](https://user-images.githubusercontent.com/7512625/36350789-f5a43838-14d8-11e8-8a90-801e69f665c1.gif) -## Existing functionalities +## Features - [x] Authentication - [x] Sign up (WebView) @@ -44,7 +42,7 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for - [x] Favor topic - [x] Upload images - [x] Emoji - - [x] Show friend list to @ + - [x] Show friend list to mention (@) - [ ] Report objectionable content - [ ] Vote - [ ] Create vote @@ -60,8 +58,8 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for - [ ] Individual - [x] View my recent topics - [x] View my favorite topics - - [ ] Update password - [x] Upload avatar + - [ ] Update password ## Try it out @@ -70,7 +68,7 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for ```bash git clone git@github.com:just4fun/stuhome.git cd stuhome -npm install +yarn ``` Then use Xcode to open this project and simply click **Run**. @@ -78,25 +76,19 @@ Then use Xcode to open this project and simply click **Run**. http://facebook.github.io/react-native/docs/running-on-device.html#running-your-app-on-ios-devices -## Run ESlint - -```bash -npm run eslint -``` - ## Todo list - ~~Update UI per new design~~ - ~~Submit to [App Store](https://itunes.apple.com/cn/app/qing-shui-he-pan-stuhome/id1190564355)~~ -- ~~Unit Testing Infrastructure~~ ([#8](https://github.com/just4fun/stuhome/pull/8)) -- ~~Replace deprecated Navigator with [React Navigation](https://github.com/react-navigation/react-navigation)~~ ([#19](https://github.com/just4fun/stuhome/pull/19)) +- ~~Replace deprecated Navigator with [React Navigation](https://github.com/react-navigation/react-navigation):~~ [#19](https://github.com/just4fun/stuhome/pull/19) +- Unit Testing Infrastructure: ~~[#8](https://github.com/just4fun/stuhome/pull/8)~~, [#40](https://github.com/just4fun/stuhome/issues/40) ## Known issues -- ~~User avatar is not displayed sometimes: [RN/issue](https://github.com/facebook/react-native/issues/5616)~~ (Fixed by this [PR](https://github.com/facebook/react-native/pull/7262) for React Native, and the patch is released in `0.26.0`) -- ~~Switching between pages is not very smooth sometimes~~ (Fixed by replacing deprecated Navigator with [React Navigation](https://github.com/react-navigation/react-navigation)) -- Emoji could not be displayed in text input: [RN/issue](https://github.com/facebook/react-native/issues/17468) -- Unit tests are not working due to deprecated property in [react-native-mock](https://github.com/RealOrangeOne/react-native-mock/pull/158) +- ~~User avatar is not displayed sometimes:~~ [RN/#5616](https://github.com/facebook/react-native/issues/5616) (Fixed by [RN/#7262](https://github.com/facebook/react-native/pull/7262), and the patch is released in `0.26.0`) +- ~~Switching between pages is not very smooth sometimes~~ (Fixed by [#19](https://github.com/just4fun/stuhome/pull/19)) +- Image could not be inserted to TextInput: [RN/#17468](https://github.com/facebook/react-native/issues/17468), [RN/#18566](https://github.com/facebook/react-native/issues/18566) +- Unit tests are not working due to deprecated property in react-native-mock. [react-native-mock/#158](https://github.com/RealOrangeOne/react-native-mock/pull/158), [#40](https://github.com/just4fun/stuhome/issues/40) ## FAQ diff --git a/package.json b/package.json index 0df24db..1999a43 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "stuhome", "version": "1.7.0", - "description": "An iOS client for http://bbs.uestc.edu.cn/ written in React Native with Redux.", + "description": "An officially recommended 3rd party iOS client for http://bbs.uestc.edu.cn/ written in react-native, redux and redux-observable.", "author": "just4fun ", "scripts": { "start": "node_modules/react-native/scripts/packager.sh",