add reveal password icon and more UI tweaks #554

Merged
akinwale merged 6 commits from pre-release into master 2019-05-28 17:00:15 +02:00
58 changed files with 736 additions and 827 deletions

386
app/package-lock.json generated
View file

@ -13,16 +13,16 @@
} }
}, },
"@babel/core": { "@babel/core": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz",
"integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==", "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==",
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.4.4", "@babel/generator": "^7.4.4",
"@babel/helpers": "^7.4.4", "@babel/helpers": "^7.4.4",
"@babel/parser": "^7.4.4", "@babel/parser": "^7.4.5",
"@babel/template": "^7.4.4", "@babel/template": "^7.4.4",
"@babel/traverse": "^7.4.4", "@babel/traverse": "^7.4.5",
"@babel/types": "^7.4.4", "@babel/types": "^7.4.4",
"convert-source-map": "^1.1.0", "convert-source-map": "^1.1.0",
"debug": "^4.1.0", "debug": "^4.1.0",
@ -276,9 +276,9 @@
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz",
"integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==" "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew=="
}, },
"@babel/plugin-external-helpers": { "@babel/plugin-external-helpers": {
"version": "7.2.0", "version": "7.2.0",
@ -612,11 +612,11 @@
} }
}, },
"@babel/plugin-transform-regenerator": { "@babel/plugin-transform-regenerator": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz",
"integrity": "sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g==", "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==",
"requires": { "requires": {
"regenerator-transform": "^0.13.4" "regenerator-transform": "^0.14.0"
} }
}, },
"@babel/plugin-transform-runtime": { "@babel/plugin-transform-runtime": {
@ -665,9 +665,9 @@
} }
}, },
"@babel/plugin-transform-typescript": { "@babel/plugin-transform-typescript": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz",
"integrity": "sha512-rwDvjaMTx09WC0rXGBRlYSSkEHOKRrecY6hEr3SVIPKII8DVWXtapNAfAyMC0dovuO+zYArcAuKeu3q9DNRfzA==", "integrity": "sha512-RPB/YeGr4ZrFKNwfuQRlMf2lxoCUaU01MTw39/OFE/RiL8HDjtn68BwEPft1P7JN4akyEmjGWAMNldOV7o9V2g==",
"requires": { "requires": {
"@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-syntax-typescript": "^7.2.0" "@babel/plugin-syntax-typescript": "^7.2.0"
@ -697,16 +697,16 @@
}, },
"dependencies": { "dependencies": {
"core-js": { "core-js": {
"version": "3.0.1", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.3.tgz",
"integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==" "integrity": "sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA=="
} }
} }
}, },
"@babel/runtime": { "@babel/runtime": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz",
"integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==", "integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==",
"requires": { "requires": {
"regenerator-runtime": "^0.13.2" "regenerator-runtime": "^0.13.2"
}, },
@ -729,15 +729,15 @@
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.4.4", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz",
"integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==", "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==",
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.4.4", "@babel/generator": "^7.4.4",
"@babel/helper-function-name": "^7.1.0", "@babel/helper-function-name": "^7.1.0",
"@babel/helper-split-export-declaration": "^7.4.4", "@babel/helper-split-export-declaration": "^7.4.4",
"@babel/parser": "^7.4.4", "@babel/parser": "^7.4.5",
"@babel/types": "^7.4.4", "@babel/types": "^7.4.4",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0", "globals": "^11.1.0",
@ -791,14 +791,14 @@
} }
}, },
"@react-native-community/async-storage": { "@react-native-community/async-storage": {
"version": "1.3.3", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.3.3.tgz", "resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.4.2.tgz",
"integrity": "sha512-mypRivxWCO3apTDWpbvc7owcz5gZH0mI60JWPJDW/Pibr3vk9T7TQPA44b8m43qc/o5cnSEJFZk6l/1T4QEM/Q==" "integrity": "sha512-gDQENh7uPLGPKbRFI07GiUXZPhm2j17K4FT308OwAmIiOKbfO/cxy0sCWB0YzD/SLw9F3D9tLBRPJY6GG9YZLw=="
}, },
"@react-native-community/cli": { "@react-native-community/cli": {
"version": "1.9.2", "version": "1.9.7",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.9.2.tgz", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.9.7.tgz",
"integrity": "sha512-wSw3g6HrSUvLZiHiWRcO++JrKdbYNRWycGbGHVCnRLsdDRsj/y152xPlvBa29C8w+1SwiiN8aGsBOO0x9hkrCg==", "integrity": "sha512-3Fw0TxB8fOVKD51kK9NN/SIonkvl8iCuUGb01RuzsrnMS76Wiu5JY3H7NhhPdvxFrrqa3vgBqJWRowAxbGJqJg==",
"requires": { "requires": {
"chalk": "^1.1.1", "chalk": "^1.1.1",
"commander": "^2.19.0", "commander": "^2.19.0",
@ -956,12 +956,12 @@
"integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=" "integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c="
}, },
"accepts": { "accepts": {
"version": "1.3.6", "version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.6.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-QsaoUD2dpVpjENy8JFpQnXP9vyzoZPmAoKrE3S6HtSB7qzSebkJNnmdY4p004FQUSSiHXPueENpoeuUW/7a8Ig==", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": { "requires": {
"mime-types": "~2.1.24", "mime-types": "~2.1.24",
"negotiator": "0.6.1" "negotiator": "0.6.2"
} }
}, },
"ansi": { "ansi": {
@ -3043,9 +3043,9 @@
"integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30000963", "version": "1.0.30000971",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz",
"integrity": "sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==", "integrity": "sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g==",
"dev": true "dev": true
}, },
"capture-exit": { "capture-exit": {
@ -3236,13 +3236,13 @@
} }
}, },
"connect": { "connect": {
"version": "3.6.6", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
"integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
"requires": { "requires": {
"debug": "2.6.9", "debug": "2.6.9",
"finalhandler": "1.1.0", "finalhandler": "1.1.2",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"utils-merge": "1.0.1" "utils-merge": "1.0.1"
} }
}, },
@ -3260,9 +3260,9 @@
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
}, },
"core-js": { "core-js": {
"version": "2.6.5", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -3270,13 +3270,13 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}, },
"cosmiconfig": { "cosmiconfig": {
"version": "5.2.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
"integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==", "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
"requires": { "requires": {
"import-fresh": "^2.0.0", "import-fresh": "^2.0.0",
"is-directory": "^0.3.1", "is-directory": "^0.3.1",
"js-yaml": "^3.13.0", "js-yaml": "^3.13.1",
"parse-json": "^4.0.0" "parse-json": "^4.0.0"
}, },
"dependencies": { "dependencies": {
@ -3428,9 +3428,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.127", "version": "1.3.137",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.127.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.137.tgz",
"integrity": "sha512-1o25iFRf/dbgauTWalEzmD1EmRN3a2CzP/K7UVpYLEBduk96LF0FyUdCcf4Ry2mAWJ1VxyblFjC93q6qlLwA2A==", "integrity": "sha512-kGi32g42a8vS/WnYE7ELJyejRT7hbr3UeOOu0WeuYuQ29gCpg9Lrf6RdcTQVXSt/v0bjCfnlb/EWOOsiKpTmkw==",
"dev": true "dev": true
}, },
"emoji-regex": { "emoji-regex": {
@ -3473,11 +3473,11 @@
} }
}, },
"errorhandler": { "errorhandler": {
"version": "1.5.0", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.0.tgz", "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz",
"integrity": "sha1-6rpkyl1UKjEayUX1gt78M2Fl2fQ=", "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==",
"requires": { "requires": {
"accepts": "~1.3.3", "accepts": "~1.3.7",
"escape-html": "~1.0.3" "escape-html": "~1.0.3"
} }
}, },
@ -3512,9 +3512,9 @@
"integrity": "sha1-qG5e5r2qFgVEddp5fM3fDFVphJE=" "integrity": "sha1-qG5e5r2qFgVEddp5fM3fDFVphJE="
}, },
"eventemitter3": { "eventemitter3": {
"version": "3.1.1", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.1.tgz", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
"integrity": "sha512-MXmFv3KYbv7MPjPeGlFCTieXB9zNvmHfy4fXzZbrdMeUUk3pxQ8SS0cJ6CcwUDZnIL3ZDa01qQFzhlusB8s51Q==" "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
}, },
"exec-sh": { "exec-sh": {
"version": "0.2.2", "version": "0.2.2",
@ -3673,16 +3673,16 @@
} }
}, },
"finalhandler": { "finalhandler": {
"version": "1.1.0", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": { "requires": {
"debug": "2.6.9", "debug": "2.6.9",
"encodeurl": "~1.0.1", "encodeurl": "~1.0.2",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"statuses": "~1.3.1", "statuses": "~1.5.0",
"unpipe": "~1.0.0" "unpipe": "~1.0.0"
} }
}, },
@ -3734,9 +3734,9 @@
} }
}, },
"flow-bin": { "flow-bin": {
"version": "0.98.0", "version": "0.98.1",
"resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.98.0.tgz", "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.98.1.tgz",
"integrity": "sha512-vuiYjBVt82eYF+dEk9Zqa8hTSDvbhl/czxzFRLZm9/XHbJnYNMTwFoNFYAQT9IQ6ACNBIbwSTIfxroieuKja7g==", "integrity": "sha512-y1YzQgbFUX4EG6h2EO8PhyJeS0VxNgER8XsTwU8IXw4KozfneSmGVgw8y3TwAOza7rVhTlHEoli1xNuNW1rhPw==",
"dev": true "dev": true
}, },
"for-in": { "for-in": {
@ -4285,9 +4285,9 @@
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
}, },
"glob": { "glob": {
"version": "7.1.3", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
"inflight": "^1.0.4", "inflight": "^1.0.4",
@ -4324,9 +4324,9 @@
} }
}, },
"globals": { "globals": {
"version": "11.11.0", "version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==" "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
}, },
"google-libphonenumber": { "google-libphonenumber": {
"version": "2.0.19", "version": "2.0.19",
@ -4426,21 +4426,15 @@
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
}, },
"http-errors": { "http-errors": {
"version": "1.6.3", "version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": { "requires": {
"depd": "~1.1.2", "depd": "~1.1.2",
"inherits": "2.0.3", "inherits": "2.0.3",
"setprototypeof": "1.1.0", "setprototypeof": "1.1.1",
"statuses": ">= 1.4.0 < 2" "statuses": ">= 1.5.0 < 2",
}, "toidentifier": "1.0.0"
"dependencies": {
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
}
} }
}, },
"iconv-lite": { "iconv-lite": {
@ -4818,8 +4812,8 @@
} }
}, },
"lbry-redux": { "lbry-redux": {
"version": "github:lbryio/lbry-redux#5cff70a26b05b40f2693bbae6bf50100a6781e50", "version": "github:lbryio/lbry-redux#a01b919c72139d82fa981df6be4e0fe902ff8f70",
"from": "github:lbryio/lbry-redux#purchase-uri-failures", "from": "github:lbryio/lbry-redux",
"requires": { "requires": {
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",
@ -4827,8 +4821,8 @@
} }
}, },
"lbryinc": { "lbryinc": {
"version": "github:lbryio/lbryinc#54ef55d430db13ecd77699d23974cf871445ebd7", "version": "github:lbryio/lbryinc#5bffcaf83d8e3191a4b95a54fbdffccf58da0a36",
"from": "github:lbryio/lbryinc#check-sync", "from": "github:lbryio/lbryinc",
"requires": { "requires": {
"reselect": "^3.0.0" "reselect": "^3.0.0"
} }
@ -5508,9 +5502,9 @@
} }
}, },
"negotiator": { "negotiator": {
"version": "0.6.1", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
}, },
"nice-try": { "nice-try": {
"version": "1.0.5", "version": "1.0.5",
@ -5526,9 +5520,9 @@
} }
}, },
"node-fetch": { "node-fetch": {
"version": "2.4.1", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.4.1.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-P9UbpFK87NyqBZzUuDBDz4f6Yiys8xm8j7ACDbi6usvFm6KItklQUKjeoqTrYS/S1k6I8oaOC2YLLDr/gg26Mw==" "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
}, },
"node-int64": { "node-int64": {
"version": "0.4.0", "version": "0.4.0",
@ -6094,9 +6088,9 @@
} }
}, },
"range-parser": { "range-parser": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
}, },
"react": { "react": {
"version": "16.8.6", "version": "16.8.6",
@ -6289,14 +6283,14 @@
"integrity": "sha512-XRHhGH5aM4lSenX4zZBa07JaszJGXeF8cv1KY314Q4qJWOihKWLpkdvwqwsBieZ2iy8DPhdAVioQzw8JLD/Okw==" "integrity": "sha512-XRHhGH5aM4lSenX4zZBa07JaszJGXeF8cv1KY314Q4qJWOihKWLpkdvwqwsBieZ2iy8DPhdAVioQzw8JLD/Okw=="
}, },
"react-native-fast-image": { "react-native-fast-image": {
"version": "5.3.0", "version": "5.4.2",
"resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.3.0.tgz", "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.4.2.tgz",
"integrity": "sha512-pqp9loZbWHW2pVcaAItV5rtEpj6RyPnk0mRlsxRZpbJvrJArJwRMd+WT8BzC+OyTDV1TOdFJCOxDyVNL9I2XTw==" "integrity": "sha512-S4E96Lwmx6z6QD3MaAuP7cNcXRLfgEUYU2GB694TbGEoOjk/FO1OnfbxfFp0vUs/klr4HJwACcwihPPxrFTt8w=="
}, },
"react-native-gesture-handler": { "react-native-gesture-handler": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.2.0.tgz", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.2.1.tgz",
"integrity": "sha512-PBsqfyUlzAQQXVEy5nDB8HpehSalhN8Vlc00VJ4RT0FDxlkbpl1otT6DxUN/shMEEuOkyS9gz80ZzWTfAmeBOQ==", "integrity": "sha512-c1+L72Vjc/bwHKcIJ8a2/88SW9l3/axcAIpg3zB1qTzwdCxHZJeQn6d58cQXHPepxFBbgfTCo60B7SipSfo+zw==",
"requires": { "requires": {
"hoist-non-react-statics": "^2.3.1", "hoist-non-react-statics": "^2.3.1",
"invariant": "^2.2.2", "invariant": "^2.2.2",
@ -6309,9 +6303,9 @@
"integrity": "sha512-ZCisGUFpPchHXsjT7ZI0anlSLPgcTmjRKXqpVnPu3RDWFXfKjuL4zpY57DX4Y8YgGZCpbf9fApN7KjVYody2Mw==" "integrity": "sha512-ZCisGUFpPchHXsjT7ZI0anlSLPgcTmjRKXqpVnPu3RDWFXfKjuL4zpY57DX4Y8YgGZCpbf9fApN7KjVYody2Mw=="
}, },
"react-native-image-zoom-viewer": { "react-native-image-zoom-viewer": {
"version": "2.2.25", "version": "2.2.26",
"resolved": "https://registry.npmjs.org/react-native-image-zoom-viewer/-/react-native-image-zoom-viewer-2.2.25.tgz", "resolved": "https://registry.npmjs.org/react-native-image-zoom-viewer/-/react-native-image-zoom-viewer-2.2.26.tgz",
"integrity": "sha512-/w3GsUD9F5c6ZE+3GC1UmE0I9yCAfTf/5Jjz5bDCvIQFp2MoMod3BQzRnZ1PjZbCq6a90eZ5rnB2Zvm1rFOgeQ==", "integrity": "sha512-Mh4+CJQCDcAumLFXLlDk8nQ5iMxNnupc9HwktsZ3I/v4HULcFPmTLDQ0HGAxjLa5foZRPnKDN06iKGsEb9raoA==",
"requires": { "requires": {
"react-native-image-pan-zoom": "^2.1.9" "react-native-image-pan-zoom": "^2.1.9"
} }
@ -6374,9 +6368,17 @@
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
"version": "3.0.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
}, },
"camelcase": { "camelcase": {
"version": "5.3.1", "version": "5.3.1",
@ -6384,24 +6386,13 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
}, },
"cliui": { "cliui": {
"version": "4.1.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"requires": { "requires": {
"string-width": "^2.1.1", "string-width": "^3.1.0",
"strip-ansi": "^4.0.0", "strip-ansi": "^5.2.0",
"wrap-ansi": "^2.0.0" "wrap-ansi": "^5.1.0"
},
"dependencies": {
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
}
} }
}, },
"cross-spawn": { "cross-spawn": {
@ -6537,29 +6528,24 @@
"emoji-regex": "^7.0.1", "emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0", "is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0" "strip-ansi": "^5.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
}
} }
}, },
"strip-ansi": { "strip-ansi": {
"version": "4.0.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": { "requires": {
"ansi-regex": "^3.0.0" "ansi-regex": "^4.1.0"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
} }
}, },
"y18n": { "y18n": {
@ -6568,11 +6554,11 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
}, },
"yargs": { "yargs": {
"version": "13.2.2", "version": "13.2.4",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==",
"requires": { "requires": {
"cliui": "^4.0.0", "cliui": "^5.0.0",
"find-up": "^3.0.0", "find-up": "^3.0.0",
"get-caller-file": "^2.0.1", "get-caller-file": "^2.0.1",
"os-locale": "^3.1.0", "os-locale": "^3.1.0",
@ -6582,13 +6568,13 @@
"string-width": "^3.0.0", "string-width": "^3.0.0",
"which-module": "^2.0.0", "which-module": "^2.0.0",
"y18n": "^4.0.0", "y18n": "^4.0.0",
"yargs-parser": "^13.0.0" "yargs-parser": "^13.1.0"
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "13.0.0", "version": "13.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.0.tgz",
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", "integrity": "sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA==",
"requires": { "requires": {
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
"decamelize": "^1.2.0" "decamelize": "^1.2.0"
@ -6597,7 +6583,7 @@
} }
}, },
"react-native-video": { "react-native-video": {
"version": "github:lbryio/react-native-video#0b2ed972f12f8d85d8febaff0b191444fe29cb3f", "version": "github:lbryio/react-native-video#7366652125f1e08c5ab128da630af0420357d33c",
"from": "github:lbryio/react-native-video#exoplayer-lbry-android", "from": "github:lbryio/react-native-video#exoplayer-lbry-android",
"requires": { "requires": {
"keymirror": "^0.1.1", "keymirror": "^0.1.1",
@ -6787,9 +6773,9 @@
"integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
}, },
"regenerate-unicode-properties": { "regenerate-unicode-properties": {
"version": "8.0.2", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz",
"integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==",
"requires": { "requires": {
"regenerate": "^1.4.0" "regenerate": "^1.4.0"
} }
@ -6800,9 +6786,9 @@
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
}, },
"regenerator-transform": { "regenerator-transform": {
"version": "0.13.4", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.0.tgz",
"integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", "integrity": "sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w==",
"requires": { "requires": {
"private": "^0.1.6" "private": "^0.1.6"
} }
@ -6888,9 +6874,9 @@
"integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=" "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc="
}, },
"resolve": { "resolve": {
"version": "1.10.1", "version": "1.11.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
"integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
"requires": { "requires": {
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
} }
@ -7316,9 +7302,9 @@
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
}, },
"send": { "send": {
"version": "0.16.2", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
"requires": { "requires": {
"debug": "2.6.9", "debug": "2.6.9",
"depd": "~1.1.2", "depd": "~1.1.2",
@ -7327,23 +7313,18 @@
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.1", "etag": "~1.8.1",
"fresh": "0.5.2", "fresh": "0.5.2",
"http-errors": "~1.6.2", "http-errors": "~1.7.2",
"mime": "1.4.1", "mime": "1.6.0",
"ms": "2.0.0", "ms": "2.1.1",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"range-parser": "~1.2.0", "range-parser": "~1.2.1",
"statuses": "~1.4.0" "statuses": "~1.5.0"
}, },
"dependencies": { "dependencies": {
"mime": { "ms": {
"version": "1.4.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
} }
} }
}, },
@ -7353,14 +7334,14 @@
"integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go="
}, },
"serve-static": { "serve-static": {
"version": "1.13.2", "version": "1.14.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
"requires": { "requires": {
"encodeurl": "~1.0.2", "encodeurl": "~1.0.2",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"send": "0.16.2" "send": "0.17.1"
} }
}, },
"set-blocking": { "set-blocking": {
@ -7395,14 +7376,14 @@
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
}, },
"setprototypeof": { "setprototypeof": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
}, },
"shaka-player": { "shaka-player": {
"version": "2.4.7", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-2.4.7.tgz", "resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-2.5.1.tgz",
"integrity": "sha512-KXYVB7snrrmcmDvusf2IIGOXZCvrlb6vXkl1q0pXP/QdUkvHm2SsW6jIXKvDz9xsvs9Pt/R7tm8POgfUOzybcQ==" "integrity": "sha512-5P1bnWQ3LTiNbt7nyf75btGAPCWW3lHRhti9Yl/yE+DowqRl8KcHkHR0t0OfERyRKO1lrPLrCjiVOgJhi9jbFw=="
}, },
"shebang-command": { "shebang-command": {
"version": "1.2.0", "version": "1.2.0",
@ -7640,9 +7621,9 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
}, },
"stacktrace-parser": { "stacktrace-parser": {
"version": "0.1.5", "version": "0.1.6",
"resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.5.tgz", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.6.tgz",
"integrity": "sha512-fjJ563lEMEXdqUH8fZR84sczWxM+Pi3bViix1n7371mFr8sL7UPewec79+IhHkN4UMmGbXoXj58WIaF7lIciRA==", "integrity": "sha512-wXhu0Z8YgCGigUtHQq+J7pjXCppk3Um5DwH4qskOKHMlJmKwuuUSm+wDAgU7t4sbVjvuDTNGwOfFKgjMEqSflA==",
"requires": { "requires": {
"type-fest": "^0.3.0" "type-fest": "^0.3.0"
} }
@ -7667,9 +7648,9 @@
} }
}, },
"statuses": { "statuses": {
"version": "1.3.1", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
}, },
"stream-buffers": { "stream-buffers": {
"version": "2.2.0", "version": "2.2.0",
@ -7842,6 +7823,11 @@
} }
} }
}, },
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"trim-right": { "trim-right": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",

View file

@ -8,8 +8,8 @@
"dependencies": { "dependencies": {
"base-64": "^0.1.0", "base-64": "^0.1.0",
"@expo/vector-icons": "^8.1.0", "@expo/vector-icons": "^8.1.0",
"lbry-redux": "lbryio/lbry-redux#purchase-uri-failures", "lbry-redux": "lbryio/lbry-redux",
"lbryinc": "lbryio/lbryinc#check-sync", "lbryinc": "lbryio/lbryinc",
"lodash": ">=4.17.11", "lodash": ">=4.17.11",
"merge": ">=1.2.1", "merge": ">=1.2.1",
"moment": "^2.22.1", "moment": "^2.22.1",
@ -26,7 +26,7 @@
"react-native-vector-icons": "^6.4.2", "react-native-vector-icons": "^6.4.2",
"react-native-video": "lbryio/react-native-video#exoplayer-lbry-android", "react-native-video": "lbryio/react-native-video#exoplayer-lbry-android",
"react-navigation": "^3.11.0", "react-navigation": "^3.11.0",
"react-navigation-redux-helpers": "^3.0.0", "react-navigation-redux-helpers": "^3.0.2",
"react-redux": "^5.0.3", "react-redux": "^5.0.3",
"redux": "^3.6.0", "redux": "^3.6.0",
"redux-persist": "^4.10.2", "redux-persist": "^4.10.2",

View file

@ -15,15 +15,14 @@ import VerificationScreen from 'page/verification';
import WalletPage from 'page/wallet'; import WalletPage from 'page/wallet';
import SearchInput from 'component/searchInput'; import SearchInput from 'component/searchInput';
import { import {
createAppContainer,
createDrawerNavigator, createDrawerNavigator,
createStackNavigator, createStackNavigator,
NavigationActions NavigationActions
} from 'react-navigation'; } from 'react-navigation';
import { import {
addListener,
createReduxContainer, createReduxContainer,
createReactNavigationReduxMiddleware, createReactNavigationReduxMiddleware,
createNavigationReducer
} from 'react-navigation-redux-helpers'; } from 'react-navigation-redux-helpers';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
@ -101,46 +100,6 @@ discoverStack.navigationOptions = ({ navigation }) => {
}; };
}; };
const trendingStack = createStackNavigator({
Trending: {
screen: TrendingPage,
navigationOptions: ({ navigation }) => ({
title: 'Trending',
header: null
})
}
});
const myLbryStack = createStackNavigator({
Downloads: {
screen: DownloadsPage,
navigationOptions: ({ navigation }) => ({
title: 'Library',
header: null
})
}
});
const mySubscriptionsStack = createStackNavigator({
Subscriptions: {
screen: SubscriptionsPage,
navigationOptions: ({ navigation }) => ({
title: 'Subscriptions',
header: null
})
}
});
const rewardsStack = createStackNavigator({
Rewards: {
screen: RewardsPage,
navigationOptions: ({ navigation }) => ({
title: 'Rewards',
header: null
})
}
});
const walletStack = createStackNavigator({ const walletStack = createStackNavigator({
Wallet: { Wallet: {
screen: WalletPage, screen: WalletPage,
@ -165,19 +124,19 @@ const drawer = createDrawerNavigator({
DiscoverStack: { screen: discoverStack, navigationOptions: { DiscoverStack: { screen: discoverStack, navigationOptions: {
title: 'Explore', drawerIcon: ({ tintColor }) => <Icon name="home" size={20} style={{ color: tintColor }} /> title: 'Explore', drawerIcon: ({ tintColor }) => <Icon name="home" size={20} style={{ color: tintColor }} />
}}, }},
TrendingStack: { screen: trendingStack, navigationOptions: { TrendingStack: { screen: TrendingPage, navigationOptions: {
title: 'Trending', drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} /> title: 'Trending', drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} />
}}, }},
MySubscriptionsStack: { screen: mySubscriptionsStack, navigationOptions: { MySubscriptionsStack: { screen: SubscriptionsPage, navigationOptions: {
title: 'Subscriptions', drawerIcon: ({ tintColor }) => <Icon name="heart" solid={true} size={20} style={{ color: tintColor }} /> title: 'Subscriptions', drawerIcon: ({ tintColor }) => <Icon name="heart" solid={true} size={20} style={{ color: tintColor }} />
}}, }},
WalletStack: { screen: walletStack, navigationOptions: { WalletStack: { screen: walletStack, navigationOptions: {
title: 'Wallet', drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} /> title: 'Wallet', drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} />
}}, }},
Rewards: { screen: rewardsStack, navigationOptions: { Rewards: { screen: RewardsPage, navigationOptions: {
drawerIcon: ({ tintColor }) => <Icon name="award" size={20} style={{ color: tintColor }} /> drawerIcon: ({ tintColor }) => <Icon name="award" size={20} style={{ color: tintColor }} />
}}, }},
MyLBRYStack: { screen: myLbryStack, navigationOptions: { MyLBRYStack: { screen: DownloadsPage, navigationOptions: {
title: 'Library', drawerIcon: ({ tintColor }) => <Icon name="download" size={20} style={{ color: tintColor }} /> title: 'Library', drawerIcon: ({ tintColor }) => <Icon name="download" size={20} style={{ color: tintColor }} />
}}, }},
Settings: { screen: SettingsPage, navigationOptions: { Settings: { screen: SettingsPage, navigationOptions: {
@ -225,10 +184,12 @@ const mainStackNavigator = new createStackNavigator({
export const AppNavigator = mainStackNavigator; export const AppNavigator = mainStackNavigator;
export const navigatorReducer = createNavigationReducer(AppNavigator);
export const reactNavigationMiddleware = createReactNavigationReduxMiddleware( export const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
state => state.nav, state => state.nav,
); );
const App = createReduxContainer(mainStackNavigator, "root");
const App = createReduxContainer(mainStackNavigator);
const appMapStateToProps = (state) => ({ const appMapStateToProps = (state) => ({
state: state.nav, state: state.nav,
}); });

View file

@ -1,26 +0,0 @@
import { connect } from 'react-redux';
import {
doUserEmailNew,
doUserEmailToVerify,
doUserResendVerificationEmail,
selectEmailNewErrorMessage,
selectEmailNewIsPending,
selectEmailToVerify,
} from 'lbryinc';
import { doToast } from 'lbry-redux';
import EmailRewardSubcard from './view';
const select = state => ({
emailToVerify: selectEmailToVerify(state),
emailNewErrorMessage: selectEmailNewErrorMessage(state),
emailNewPending: selectEmailNewIsPending(state)
});
const perform = dispatch => ({
addUserEmail: email => dispatch(doUserEmailNew(email)),
setEmailToVerify: email => dispatch(doUserEmailToVerify(email)),
notify: data => dispatch(doToast(data)),
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email))
});
export default connect(select, perform)(EmailRewardSubcard);

View file

@ -1,106 +0,0 @@
// @flow
import React from 'react';
import {
ActivityIndicator,
Text,
TextInput,
TouchableOpacity,
View
} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Button from 'component/button';
import Colors from 'styles/colors';
import Constants from 'constants';
import Link from 'component/link';
import rewardStyle from 'styles/reward';
class EmailRewardSubcard extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
email: null,
emailAlreadySet: false,
previousEmail: null,
verfiyStarted: false
};
}
componentDidMount() {
const { setEmailToVerify } = this.props;
AsyncStorage.getItem(Constants.KEY_FIRST_RUN_EMAIL).then(email => setEmailToVerify(email));
}
componentWillReceiveProps(nextProps) {
const { emailNewErrorMessage, emailNewPending, emailToVerify } = nextProps;
const { notify } = this.props;
if (emailToVerify && emailToVerify.trim().length > 0 && !this.state.email && !this.state.previousEmail) {
this.setState({ email: emailToVerify, previousEmail: emailToVerify, emailAlreadySet: true });
}
if (this.state.verifyStarted && !emailNewPending) {
if (emailNewErrorMessage) {
notify({ message: String(emailNewErrorMessage), isError: true });
this.setState({ verifyStarted: false });
} else {
notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
}
}
}
handleChangeText = (text) => {
// save the value to the state email
this.setState({ email: text });
AsyncStorage.setItem(Constants.KEY_FIRST_RUN_EMAIL, text);
}
onSendVerificationPressed = () => {
if (this.state.verifyStarted) {
return;
}
const { addUserEmail, notify, resendVerificationEmail } = this.props;
const { email } = this.state;
if (!email || email.trim().length === 0 || email.indexOf('@') === -1) {
return notify({
message: 'Please provide a valid email address to continue.',
});
}
this.setState({ verifyStarted: true });
if (this.state.emailAlreadySet && this.state.previousEmail === email) {
// resend verification email if there was one previously set (and it wasn't changed)
resendVerificationEmail(email);
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
return;
}
addUserEmail(email);
}
render() {
const { emailNewPending } = this.props;
return (
<View style={rewardStyle.subcard}>
<Text style={rewardStyle.subtitle}>Pending action: Verify Email</Text>
<Text style={rewardStyle.subcardText}>Please provide an email address to verify. If you received a link previously, please follow the instructions in the email to complete verification.</Text>
<TextInput style={rewardStyle.subcardTextInput}
placeholder="you@example.com"
underlineColorAndroid="transparent"
value={this.state.email}
onChangeText={text => this.handleChangeText(text)} />
{!this.state.verifyStarted && <Button style={rewardStyle.actionButton}
text={"Send verification email"}
onPress={this.onSendVerificationPressed} />}
{this.state.verifyStarted && emailNewPending &&
<ActivityIndicator size={"small"} color={Colors.LbryGreen} style={rewardStyle.loading} />}
</View>
);
}
};
export default EmailRewardSubcard;

View file

@ -411,14 +411,8 @@ class MediaPlayer extends React.PureComponent {
return ( return (
<View style={styles} onLayout={onLayout}> <View style={styles} onLayout={onLayout}>
<Video source={{ <Video source={{ uri: source }}
uri: source, bufferConfig={{ minBufferMs: 15000, maxBufferMs: 60000, bufferForPlaybackMs: 5000, bufferForPlaybackAfterRebufferMs: 5000 }}
headers: {
"Save-Data": "on",
"Accept": "*/*"
}
}}
bufferConfig={{ minBufferMs: 3000, maxBufferMs: 60000, bufferForPlaybackMs: 3000, bufferForPlaybackAfterRebufferMs: 3000 }}
ref={(ref: Video) => { this.video = ref; }} ref={(ref: Video) => { this.video = ref; }}
resizeMode={this.state.resizeMode} resizeMode={this.state.resizeMode}
playInBackground={this.state.backgroundPlayEnabled} playInBackground={this.state.backgroundPlayEnabled}

View file

@ -1,28 +0,0 @@
import { connect } from 'react-redux';
import { doToast } from 'lbry-redux';
import {
doUserPhoneNew,
doUserPhoneVerify,
selectPhoneNewErrorMessage,
selectPhoneNewIsPending,
selectPhoneToVerify,
selectPhoneVerifyIsPending,
selectPhoneVerifyErrorMessage
} from 'lbryinc';
import PhoneNumberRewardSubcard from './view';
const select = state => ({
phoneVerifyErrorMessage: selectPhoneVerifyErrorMessage(state),
phoneVerifyIsPending: selectPhoneVerifyIsPending(state),
phone: selectPhoneToVerify(state),
phoneNewErrorMessage: selectPhoneNewErrorMessage(state),
phoneNewIsPending: selectPhoneNewIsPending(state),
});
const perform = dispatch => ({
addUserPhone: (phone, country_code) => dispatch(doUserPhoneNew(phone, country_code)),
verifyPhone: (verificationCode) => dispatch(doUserPhoneVerify(verificationCode)),
notify: data => dispatch(doToast(data)),
});
export default connect(select, perform)(PhoneNumberRewardSubcard);

View file

@ -1,235 +0,0 @@
// @flow
import React from 'react';
import {
ActivityIndicator,
DeviceEventEmitter,
NativeModules,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import Button from 'component/button';
import Colors from 'styles/colors';
import Constants from 'constants';
import CountryPicker from 'react-native-country-picker-modal';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link';
import PhoneInput from 'react-native-phone-input';
import rewardStyle from 'styles/reward';
class PhoneNumberRewardSubcard extends React.PureComponent {
phoneInput = null;
picker = null;
constructor(props) {
super(props);
this.state = {
canReceiveSms: false,
cca2: 'US',
codeVerifyStarted: false,
codeVerifySuccessful: false,
countryCode: null,
newPhoneAdded: false,
number: null,
phoneVerifyFailed: false,
verificationCode: null,
};
}
componentDidMount() {
//DeviceEventEmitter.addListener('onReceiveSmsPermissionGranted', this.receiveSmsPermissionGranted);
DeviceEventEmitter.addListener('onVerificationCodeReceived', this.receiveVerificationCode);
const { phone } = this.props;
if (phone && String(phone).trim().length > 0) {
this.setState({ newPhoneAdded: true });
}
/*if (NativeModules.UtilityModule) {
NativeModules.UtilityModule.canReceiveSms().then(canReceiveSms => this.setState({ canReceiveSms }));
}*/
}
componentWillUnmount() {
//DeviceEventEmitter.removeListener('onReceiveSmsPermissionGranted', this.receiveSmsPermissionGranted);
DeviceEventEmitter.removeListener('onVerificationCodeReceived', this.receiveVerificationCode);
}
componentDidUpdate(prevProps) {
const {
phoneVerifyIsPending,
phoneVerifyErrorMessage,
notify,
phoneNewErrorMessage,
phoneNewIsPending,
onPhoneVerifySuccessful
} = this.props;
if (!phoneNewIsPending && (phoneNewIsPending !== prevProps.phoneNewIsPending)) {
if (phoneNewErrorMessage) {
notify({ message: String(phoneNewErrorMessage) });
this.setState({ phoneVerifyFailed: true });
} else {
this.setState({ newPhoneAdded: true, phoneVerifyFailed: false });
}
}
if (!phoneVerifyIsPending && (phoneVerifyIsPending !== prevProps.phoneVerifyIsPending)) {
if (phoneVerifyErrorMessage) {
notify({ message: String(phoneVerifyErrorMessage) });
this.setState({ codeVerifyStarted: false, phoneVerifyFailed: true });
} else {
notify({ message: 'Your phone number was successfully verified.' });
this.setState({ codeVerifySuccessful: true, phoneVerifyFailed: false });
if (onPhoneVerifySuccessful) {
onPhoneVerifySuccessful();
}
}
}
}
receiveVerificationCode = (evt) => {
if (!this.state.newPhoneAdded || this.state.codeVerifySuccessful) {
return;
}
const { verifyPhone } = this.props;
this.setState({ codeVerifyStarted: true });
verifyPhone(evt.code);
}
onSendTextPressed = () => {
const { addUserPhone, notify } = this.props;
if (!this.phoneInput.isValidNumber()) {
return notify({
message: 'Please provide a valid telephone number.',
});
}
this.setState({ phoneVerifyFailed: false });
const countryCode = this.phoneInput.getCountryCode();
const number = this.phoneInput.getValue().replace('+' + countryCode, '');
this.setState({ countryCode, number });
addUserPhone(number, countryCode);
}
onVerifyPressed = () => {
if (this.state.codeVerifyStarted) {
return;
}
const { verifyPhone } = this.props;
this.setState({ codeVerifyStarted: true, phoneVerifyFailed: false });
verifyPhone(this.state.verificationCode);
}
onPressFlag = () => {
if (this.picker) {
this.picker.openModal();
}
}
selectCountry(country) {
this.phoneInput.selectCountry(country.cca2.toLowerCase());
this.setState({ cca2: country.cca2 });
}
handleChangeText = (text) => {
this.setState({ verificationCode: text });
};
render() {
const {
phoneVerifyIsPending,
phoneVerifyErrorMessage,
phone,
phoneErrorMessage,
phoneNewIsPending
} = this.props;
if (this.state.codeVerifySuccessful) {
return null;
}
return (
<View style={rewardStyle.subcard}>
<Text style={rewardStyle.subtitle}>Pending action: Verify Phone Number</Text>
<View style={rewardStyle.phoneVerificationContainer}>
{!this.state.newPhoneAdded &&
<View>
<Text style={[rewardStyle.bottomMarginMedium, rewardStyle.subcardText]}>Please enter your phone number to continue.</Text>
<PhoneInput
ref={(ref) => { this.phoneInput = ref; }}
style={StyleSheet.flatten(rewardStyle.phoneInput)}
textProps={{ placeholder: '(phone number)' }}
textStyle={StyleSheet.flatten(rewardStyle.phoneInputText)}
onPressFlag={this.onPressFlag} />
{!phoneNewIsPending &&
<Button
style={[rewardStyle.actionButton, rewardStyle.topMarginMedium]}
text={"Send verification text"}
onPress={this.onSendTextPressed} />}
{phoneNewIsPending &&
<ActivityIndicator
style={[rewardStyle.loading, rewardStyle.topMarginMedium]}
size="small"
color={Colors.LbryGreen} />}
</View>}
{this.state.newPhoneAdded &&
<View>
{!phoneVerifyIsPending && !this.codeVerifyStarted &&
<View>
<Text style={[rewardStyle.bottomMarginSmall, rewardStyle.subcardText]}>
Please enter the verification code.
</Text>
<TextInput
style={rewardStyle.verificationCodeInput}
keyboardType="numeric"
placeholder="0000"
underlineColorAndroid="transparent"
value={this.state.verificationCode}
onChangeText={text => this.handleChangeText(text)}
/>
<Button
style={[rewardStyle.actionButton, rewardStyle.topMarginSmall ]}
text={"Verify"}
onPress={this.onVerifyPressed} />
</View>
}
{phoneVerifyIsPending &&
<View>
<Text style={rewardStyle.subcardText}>Verifying your phone number...</Text>
<ActivityIndicator
color={Colors.LbryGreen}
size="small"
style={[rewardStyle.loading, rewardStyle.topMarginMedium]} />
</View>}
</View>
}
{this.state.phoneVerifyFailed &&
<View style={rewardStyle.failureFootnote}>
<Text style={rewardStyle.subcardText}>
Sorry, we were unable to verify your phone number. Please go to <Link style={rewardStyle.textLink} href="http://chat.lbry.com" text="chat.lbry.com" /> for manual verification if this keeps happening.
</Text>
</View>}
</View>
<CountryPicker
ref={(picker) => { this.picker = picker; }}
cca2={this.state.cca2}
filterable={true}
onChange={value => this.selectCountry(value)}
showCallingCode={true}
translation="eng">
<View />
</CountryPicker>
</View>
);
}
};
export default PhoneNumberRewardSubcard;

View file

@ -1,12 +1,18 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doUpdateSearchQuery, selectSearchState as selectSearch, selectSearchSuggestions } from 'lbry-redux'; import {
doUpdateSearchQuery,
selectSearchState as selectSearch,
selectSearchValue,
selectSearchSuggestions
} from 'lbry-redux';
import UriBar from './view'; import UriBar from './view';
const select = state => { const select = state => {
const { ...searchState } = selectSearch(state); const { ...searchState } = selectSearch(state);
return { return {
...searchState, ...searchState,
query: selectSearchValue(state),
suggestions: selectSearchSuggestions(state) suggestions: selectSearchSuggestions(state)
}; };
}; };

View file

@ -99,9 +99,32 @@ class UriBar extends React.PureComponent {
} }
} }
handleSubmitEditing = () => {
const { navigation, onSearchSubmitted, updateSearchQuery } = this.props;
if (this.state.inputText) {
let inputText = this.state.inputText;
if (inputText.startsWith('lbry://') && isURIValid(inputText)) {
// if it's a URI (lbry://...), open the file page
const uri = normalizeURI(inputText);
navigateToUri(navigation, uri);
} else {
updateSearchQuery(inputText);
// Not a URI, default to a search request
if (onSearchSubmitted) {
// Only the search page sets the onSearchSubmitted prop, so call this prop if set
onSearchSubmitted(inputText);
return;
}
// Open the search page with the query populated
navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: inputText }});
}
}
}
render() { render() {
const { navigation, onSearchSubmitted, suggestions, updateSearchQuery, value } = this.props; const { navigation, suggestions, query, searchView, value } = this.props;
if (this.state.currentValue === null) { if (value && this.state.currentValue === null) {
this.setState({ currentValue: value }); this.setState({ currentValue: value });
} }
@ -127,7 +150,7 @@ class UriBar extends React.PureComponent {
underlineColorAndroid={'transparent'} underlineColorAndroid={'transparent'}
numberOfLines={1} numberOfLines={1}
clearButtonMode={'while-editing'} clearButtonMode={'while-editing'}
value={this.state.currentValue} value={searchView ? query : this.state.currentValue}
returnKeyType={'go'} returnKeyType={'go'}
inlineImageLeft={'baseline_search_black_24'} inlineImageLeft={'baseline_search_black_24'}
inlineImagePadding={16} inlineImagePadding={16}
@ -137,26 +160,7 @@ class UriBar extends React.PureComponent {
this.setSelection(); this.setSelection();
}} }}
onChangeText={this.handleChangeText} onChangeText={this.handleChangeText}
onSubmitEditing={() => { onSubmitEditing={this.handleSubmitEditing}/>
if (this.state.inputText) {
let inputText = this.state.inputText;
if (inputText.startsWith('lbry://') && isURIValid(inputText)) {
// if it's a URI (lbry://...), open the file page
const uri = normalizeURI(inputText);
navigateToUri(navigation, uri);
} else {
// Not a URI, default to a search request
if (onSearchSubmitted) {
// Only the search page sets the onSearchSubmitted prop, so call this prop if set
onSearchSubmitted(inputText);
return;
}
// Open the search page with the query populated
navigation.navigate({ routeName: 'Search', key: 'searchPage', params: { searchQuery: inputText }});
}
}
}}/>
{(this.state.focused && !this.state.directSearch) && ( {(this.state.focused && !this.state.directSearch) && (
<View style={uriBarStyle.suggestions}> <View style={uriBarStyle.suggestions}>
<FlatList style={uriBarStyle.suggestionList} <FlatList style={uriBarStyle.suggestionList}

View file

@ -15,7 +15,11 @@ class WalletSyncDriver extends React.PureComponent<Props> {
return ( return (
<View style={walletStyle.syncDriverCard}> <View style={walletStyle.syncDriverCard}>
<Text style={walletStyle.syncDriverTitle}>Wallet sync is {deviceWalletSynced ? 'on' : 'off'}.</Text> <View style={walletStyle.syncDriverRow}>
<Text style={walletStyle.syncDriverTitle}>Wallet sync is {deviceWalletSynced ? 'on' : 'off'}.</Text>
{!deviceWalletSynced &&
<Link text="Sync FAQ" href="https://lbry.com/faq/how-to-backup-wallet#sync" style={walletStyle.syncDriverText} />}
</View>
{!deviceWalletSynced && {!deviceWalletSynced &&
<View style={walletStyle.actionRow}> <View style={walletStyle.actionRow}>
<Button style={walletStyle.enrollButton} theme={"light"} text={"Enable"} onPress={this.onEnableSyncPressed} /> <Button style={walletStyle.enrollButton} theme={"light"} text={"Enable"} onPress={this.onEnableSyncPressed} />

View file

@ -34,6 +34,10 @@ const Constants = {
ACTION_POP_DRAWER_STACK: "POP_DRAWER_STACK", ACTION_POP_DRAWER_STACK: "POP_DRAWER_STACK",
ACTION_SET_PLAYER_VISIBLE: "SET_PLAYER_VISIBLE", ACTION_SET_PLAYER_VISIBLE: "SET_PLAYER_VISIBLE",
ACTION_REACT_NAVIGATION_RESET: "Navigation/RESET",
ACTION_REACT_NAVIGATION_NAVIGATE: "Navigation/NAVIGATE",
ACTION_REACT_NAVIGATION_REPLACE: "Navigation/REPLACE",
PAGE_REWARDS: "rewards", PAGE_REWARDS: "rewards",
PAGE_SETTINGS: "settings", PAGE_SETTINGS: "settings",
PAGE_TRENDING: "trending", PAGE_TRENDING: "trending",
@ -50,10 +54,18 @@ const Constants = {
DRAWER_ROUTE_SEARCH: "Search", DRAWER_ROUTE_SEARCH: "Search",
DRAWER_ROUTE_TRANSACTION_HISTORY: "TransactionHistory", DRAWER_ROUTE_TRANSACTION_HISTORY: "TransactionHistory",
SUBSCRIPTIONS_VIEW_ALL: 'view_all', FULL_ROUTE_NAME_DISCOVER: "DiscoverStack",
SUBSCRIPTIONS_VIEW_LATEST_FIRST: 'view_latest_first', FULL_ROUTE_NAME_TRENDING: "TrendingStack",
FULL_ROUTE_NAME_MY_SUBSCRIPTIONS: "MySubscriptionsStack",
FULL_ROUTE_NAME_WALLET: "WalletStack",
FULL_ROUTE_NAME_MY_LBRY: "MyLBRYStack",
PLAY_STORE_URL: 'https://play.google.com/store/apps/details?id=io.lbry.browser', ROUTE_FILE: "File",
SUBSCRIPTIONS_VIEW_ALL: "view_all",
SUBSCRIPTIONS_VIEW_LATEST_FIRST: "view_latest_first",
PLAY_STORE_URL: "https://play.google.com/store/apps/details?id=io.lbry.browser",
RATING_REMINDER_INTERVAL: 604800, // 7 days (7 * 24 * 3600s) RATING_REMINDER_INTERVAL: 604800, // 7 days (7 * 24 * 3600s)
}; };

View file

@ -28,9 +28,8 @@ import {
userReducer userReducer
} from 'lbryinc'; } from 'lbryinc';
import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { AppNavigator } from 'component/AppNavigator'; import AppWithNavigationState, { AppNavigator, navigatorReducer, reactNavigationMiddleware } from 'component/AppNavigator';
import { persistStore, autoRehydrate } from 'redux-persist'; import { persistStore, autoRehydrate } from 'redux-persist';
import AppWithNavigationState, { reactNavigationMiddleware } from './component/AppNavigator';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import FilesystemStorage from 'redux-persist-filesystem-storage'; import FilesystemStorage from 'redux-persist-filesystem-storage';
import createCompressor from 'redux-persist-transform-compress'; import createCompressor from 'redux-persist-transform-compress';
@ -76,13 +75,9 @@ function enableBatching(reducer) {
}; };
} }
const router = AppNavigator.router; /*const router = AppNavigator.router;
const navAction = router.getActionForPathAndParams('FirstRun'); const navAction = router.getActionForPathAndParams('FirstRun');
const initialNavState = router.getStateForAction(navAction); const initialNavState = router.getStateForAction(navAction);*/
const navigatorReducer = (state = initialNavState, action) => {
const nextState = AppNavigator.router.getStateForAction(action, state);
return nextState || state;
};
const reducers = combineReducers({ const reducers = combineReducers({
auth: authReducer, auth: authReducer,

View file

@ -2,14 +2,15 @@ import { connect } from 'react-redux';
import { doToast } from 'lbry-redux'; import { doToast } from 'lbry-redux';
import { doFetchAccessToken, selectAccessToken, selectUserEmail } from 'lbryinc'; import { doFetchAccessToken, selectAccessToken, selectUserEmail } from 'lbryinc';
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectDrawerStack } from 'redux/selectors/drawer'; import { selectCurrentRoute, selectDrawerStack } from 'redux/selectors/drawer';
import AboutPage from './view'; import AboutPage from './view';
import Constants from 'constants'; import Constants from 'constants';
const select = state => ({ const select = state => ({
accessToken: selectAccessToken(state), accessToken: selectAccessToken(state),
userEmail: selectUserEmail(state), currentRoute: selectCurrentRoute(state),
drawerStack: selectDrawerStack(state), drawerStack: selectDrawerStack(state),
userEmail: selectUserEmail(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({

View file

@ -2,6 +2,7 @@ import React from 'react';
import { Lbry } from 'lbry-redux'; import { Lbry } from 'lbry-redux';
import { NativeModules, Text, View, ScrollView } from 'react-native'; import { NativeModules, Text, View, ScrollView } from 'react-native';
import { navigateBack } from 'utils/helper'; import { navigateBack } from 'utils/helper';
import Constants from 'constants';
import Link from 'component/link'; import Link from 'component/link';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import aboutStyle from 'styles/about'; import aboutStyle from 'styles/about';
@ -13,7 +14,32 @@ class AboutPage extends React.PureComponent {
versionInfo: null versionInfo: null
}; };
didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
componentDidMount() { componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.DRAWER_ROUTE_ABOUT === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible } = this.props; const { pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();

View file

@ -6,13 +6,15 @@ import {
selectIsFetchingFileList, selectIsFetchingFileList,
} from 'lbry-redux'; } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import DownloadsPage from './view'; import DownloadsPage from './view';
const select = (state) => ({ const select = (state) => ({
claims: selectMyClaimsWithoutChannels(state),
currentRoute: selectCurrentRoute(state),
fileInfos: selectFileInfosDownloaded(state), fileInfos: selectFileInfosDownloaded(state),
fetching: selectIsFetchingFileList(state), fetching: selectIsFetchingFileList(state),
claims: selectMyClaimsWithoutChannels(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({

View file

@ -11,6 +11,7 @@ import {
} from 'react-native'; } from 'react-native';
import { navigateToUri, uriFromFileInfo } from 'utils/helper'; import { navigateToUri, uriFromFileInfo } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import FileListItem from 'component/fileListItem'; import FileListItem from 'component/fileListItem';
import FloatingWalletBalance from 'component/floatingWalletBalance'; import FloatingWalletBalance from 'component/floatingWalletBalance';
@ -24,13 +25,38 @@ class DownloadsPage extends React.PureComponent {
title: 'Downloads' title: 'Downloads'
}; };
componentDidMount() { didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { fileList, pushDrawerStack, setPlayerVisible } = this.props; const { fileList, pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
fileList(); fileList();
} }
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.FULL_ROUTE_NAME_MY_LBRY === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
render() { render() {
const { fetching, fileInfos, navigation } = this.props; const { fetching, fileInfos, navigation } = this.props;
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0; const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
@ -60,14 +86,8 @@ class DownloadsPage extends React.PureComponent {
onPress={() => navigateToUri(navigation, uriFromFileInfo(item), { autoplay: true })} /> onPress={() => navigateToUri(navigation, uriFromFileInfo(item), { autoplay: true })} />
) )
} }
data={fileInfos.sort((a, b) => { data={fileInfos}
// TODO: Implement sort based on user selection keyExtractor={(item, index) => item.outpoint}
if (!a.completed && b.completed) return -1;
if (a.completed && !b.completed) return 1;
if (a.metadata.title === b.metadata.title) return 0;
return (a.metadata.title < b.metadata.title) ? -1 : 1;
})}
keyExtractor={(item, index) => item.download_path}
/> />
</View>} </View>}
<FloatingWalletBalance navigation={navigation} /> <FloatingWalletBalance navigation={navigation} />

View file

@ -22,8 +22,9 @@ import { navigateBack, navigateToUri } from 'utils/helper';
import Icon from 'react-native-vector-icons/FontAwesome5'; import Icon from 'react-native-vector-icons/FontAwesome5';
import ImageViewer from 'react-native-image-zoom-viewer'; import ImageViewer from 'react-native-image-zoom-viewer';
import Button from 'component/button'; import Button from 'component/button';
import Colors from 'styles/colors';
import ChannelPage from 'page/channel'; import ChannelPage from 'page/channel';
import Colors from 'styles/colors';
import Constants from 'constants';
import DateTime from 'component/dateTime'; import DateTime from 'component/dateTime';
import FileDownloadButton from 'component/fileDownloadButton'; import FileDownloadButton from 'component/fileDownloadButton';
import FileItemMedia from 'component/fileItemMedia'; import FileItemMedia from 'component/fileItemMedia';
@ -81,7 +82,14 @@ class FilePage extends React.PureComponent {
}; };
} }
componentDidMount() { didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
onComponentFocused = () => {
StatusBar.setHidden(false); StatusBar.setHidden(false);
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted); DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
@ -105,9 +113,14 @@ class FilePage extends React.PureComponent {
} }
} }
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const { const {
claim, claim,
currentRoute,
failedPurchaseUris: prevFailedPurchaseUris, failedPurchaseUris: prevFailedPurchaseUris,
purchasedUris: prevPurchasedUris, purchasedUris: prevPurchasedUris,
navigation, navigation,
@ -115,7 +128,18 @@ class FilePage extends React.PureComponent {
notify notify
} = this.props; } = this.props;
const { uri } = navigation.state.params; const { uri } = navigation.state.params;
const { failedPurchaseUris, fileInfo, purchasedUris, purchaseUriErrorMessage, streamingUrl } = nextProps; const {
currentRoute: prevRoute,
failedPurchaseUris,
fileInfo,
purchasedUris,
purchaseUriErrorMessage,
streamingUrl
} = nextProps;
if (Constants.ROUTE_FILE === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
if (failedPurchaseUris.includes(uri) && !purchasedUris.includes(uri)) { if (failedPurchaseUris.includes(uri) && !purchasedUris.includes(uri)) {
if (purchaseUriErrorMessage && purchaseUriErrorMessage.trim().length > 0) { if (purchaseUriErrorMessage && purchaseUriErrorMessage.trim().length > 0) {
@ -131,6 +155,10 @@ class FilePage extends React.PureComponent {
const { nout, txid } = claim; const { nout, txid } = claim;
const outpoint = `${txid}:${nout}`; const outpoint = `${txid}:${nout}`;
NativeModules.UtilityModule.queueDownload(outpoint); NativeModules.UtilityModule.queueDownload(outpoint);
// If the media is playable, file/view will be done in onPlaybackStarted
if (!isPlayable && !this.state.fileViewLogged) {
this.logFileView(uri, claim);
}
} }
NativeModules.UtilityModule.checkDownloads(); NativeModules.UtilityModule.checkDownloads();
} }
@ -160,16 +188,6 @@ class FilePage extends React.PureComponent {
uri: this.state.uri uri: this.state.uri
}; };
} }
const prevFileInfo = prevProps.fileInfo;
if (!prevFileInfo && fileInfo) {
const mediaType = Lbry.getMediaType(contentType);
const isPlayable = mediaType === 'video' || mediaType === 'audio';
// If the media is playable, file/view will be done in onPlaybackStarted
if (!isPlayable && !this.state.fileViewLogged) {
this.logFileView(uri, claim);
}
}
} }
fetchFileInfo(props) { fetchFileInfo(props) {
@ -276,6 +294,9 @@ class FilePage extends React.PureComponent {
utility.keepAwakeOff(); utility.keepAwakeOff();
utility.showNavigationBar(); utility.showNavigationBar();
} }
if (this.didFocusListener) {
this.didFocusListener.remove();
}
if (window.currentMediaInfo) { if (window.currentMediaInfo) {
window.currentMediaInfo = null; window.currentMediaInfo = null;
} }
@ -313,6 +334,9 @@ class FilePage extends React.PureComponent {
playerUriForFileInfo = (fileInfo) => { playerUriForFileInfo = (fileInfo) => {
const { streamingUrl } = this.props; const { streamingUrl } = this.props;
if (fileInfo && fileInfo.download_path) {
return this.getEncodedDownloadPath(fileInfo);
}
if (streamingUrl) { if (streamingUrl) {
return streamingUrl; return streamingUrl;
} }
@ -320,10 +344,6 @@ class FilePage extends React.PureComponent {
return this.state.currentStreamUrl; return this.state.currentStreamUrl;
} }
if (fileInfo && fileInfo.download_path) {
return this.getEncodedDownloadPath(fileInfo);
}
return null; return null;
} }
@ -402,9 +422,9 @@ class FilePage extends React.PureComponent {
this.startTime = null; this.startTime = null;
} }
const { fileInfo, navigation } = this.props; const { claim, navigation } = this.props;
const { uri } = navigation.state.params; const { uri } = navigation.state.params;
this.logFileView(uri, fileInfo, timeToStartMillis); this.logFileView(uri, claim, timeToStartMillis);
let payload = { 'uri': uri }; let payload = { 'uri': uri };
if (!isNaN(timeToStart)) { if (!isNaN(timeToStart)) {
@ -560,7 +580,8 @@ class FilePage extends React.PureComponent {
const isPlayable = mediaType === 'video' || mediaType === 'audio'; const isPlayable = mediaType === 'video' || mediaType === 'audio';
const { height, channel_name: channelName, value } = claim; const { height, channel_name: channelName, value } = claim;
const showActions = !this.state.streamingMode && !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView; const showActions = !this.state.streamingMode && !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView;
const showFileActions = (completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes)); const showFileActions = (fileInfo && fileInfo.download_path) &&
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id; const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
const canSendTip = this.state.tipAmount > 0; const canSendTip = this.state.tipAmount > 0;
const fullChannelUri = channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName; const fullChannelUri = channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName;
@ -703,6 +724,7 @@ class FilePage extends React.PureComponent {
<ScrollView <ScrollView
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer} style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
contentContainerstyle={showActions ? null : filePageStyle.scrollContent} contentContainerstyle={showActions ? null : filePageStyle.scrollContent}
keyboardShouldPersistTaps={'handled'}
ref={(ref) => { this.scrollView = ref; }}> ref={(ref) => { this.scrollView = ref; }}>
<TouchableWithoutFeedback style={filePageStyle.titleTouch} <TouchableWithoutFeedback style={filePageStyle.titleTouch}
onPress={() => this.setState({ showDescription: !this.state.showDescription })}> onPress={() => this.setState({ showDescription: !this.state.showDescription })}>

View file

@ -108,6 +108,7 @@ class EmailCollectPage extends React.PureComponent {
<TextInput style={firstRunStyle.emailInput} <TextInput style={firstRunStyle.emailInput}
placeholder={this.state.placeholder} placeholder={this.state.placeholder}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
selectionColor={Colors.NextLbryGreen}
value={this.state.email} value={this.state.email}
onChangeText={text => this.handleChangeText(text)} onChangeText={text => this.handleChangeText(text)}
onFocus={() => { onFocus={() => {

View file

@ -8,6 +8,7 @@ import {
Platform, Platform,
Text, Text,
TextInput, TextInput,
TouchableOpacity,
View View
} from 'react-native'; } from 'react-native';
import { BarPasswordStrengthDisplay } from 'react-native-password-strength-meter'; import { BarPasswordStrengthDisplay } from 'react-native-password-strength-meter';
@ -15,6 +16,7 @@ import AsyncStorage from '@react-native-community/async-storage';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants';
import firstRunStyle from 'styles/firstRun'; import firstRunStyle from 'styles/firstRun';
import Icon from 'react-native-vector-icons/FontAwesome5';
const firstRunMargins = 80; const firstRunMargins = 80;
@ -24,7 +26,8 @@ class WalletPage extends React.PureComponent {
placeholder: 'password', placeholder: 'password',
statusTries: 0, statusTries: 0,
walletReady: false, walletReady: false,
hasCheckedSync: false hasCheckedSync: false,
revealPassword: false
}; };
componentDidMount() { componentDidMount() {
@ -82,31 +85,39 @@ class WalletPage extends React.PureComponent {
{hasSyncedWallet ? "Please enter the password you used to secure your wallet." : {hasSyncedWallet ? "Please enter the password you used to secure your wallet." :
"Please enter a password to secure your account and wallet."} "Please enter a password to secure your account and wallet."}
</Text> </Text>
<TextInput style={firstRunStyle.passwordInput} <View style={firstRunStyle.passwordInputContainer}>
placeholder={this.state.placeholder} <TextInput style={firstRunStyle.passwordInput}
underlineColorAndroid="transparent" placeholder={this.state.placeholder}
secureTextEntry={true} underlineColorAndroid="transparent"
value={this.state.password} selectionColor={Colors.NextLbryGreen}
onChangeText={text => this.handleChangeText(text)} secureTextEntry={!this.state.revealPassword}
onFocus={() => { value={this.state.password}
if (!this.state.password || this.state.password.length === 0) { onChangeText={text => this.handleChangeText(text)}
this.setState({ placeholder: '' }); onFocus={() => {
} if (!this.state.password || this.state.password.length === 0) {
}} this.setState({ placeholder: '' });
onBlur={() => { }
if (!this.state.password || this.state.password.length === 0) { }}
this.setState({ placeholder: 'password' }); onBlur={() => {
} if (!this.state.password || this.state.password.length === 0) {
}} this.setState({ placeholder: 'password' });
/> }
}}
/>
<TouchableOpacity
style={firstRunStyle.revealPasswordIcon}
onPress={() => this.setState({ revealPassword: !this.state.revealPassword })}>
<Icon name={this.state.revealPassword ? "eye-slash" : "eye"} size={16} style={firstRunStyle.revealIcon} />
</TouchableOpacity>
</View>
{(!hasSyncedWallet && this.state.password && this.state.password.trim().length) > 0 && {(!hasSyncedWallet && this.state.password && this.state.password.trim().length) > 0 &&
<View style={firstRunStyle.passwordStrength}> <View style={firstRunStyle.passwordStrength}>
<BarPasswordStrengthDisplay <BarPasswordStrengthDisplay
width={Dimensions.get('window').width - firstRunMargins} width={Dimensions.get('window').width - firstRunMargins}
minLength={1} minLength={1}
password={this.state.password} /> password={this.state.password} />
</View>} </View>}
<Text style={firstRunStyle.infoParagraph}>Note: for wallet security purposes, LBRY is unable to reset your password.</Text> <Text style={firstRunStyle.infoParagraph}>Note: for wallet security purposes, LBRY is unable to reset your password.</Text>
</View> </View>
); );

View file

@ -11,15 +11,17 @@ import {
} from 'lbryinc'; } from 'lbryinc';
import { doToast } from 'lbry-redux'; import { doToast } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import RewardsPage from './view'; import RewardsPage from './view';
const select = state => ({ const select = state => ({
claimed: selectClaimedRewards(state),
currentRoute: selectCurrentRoute(state),
emailVerifyErrorMessage: selectEmailVerifyErrorMessage(state), emailVerifyErrorMessage: selectEmailVerifyErrorMessage(state),
emailVerifyPending: selectEmailVerifyIsPending(state), emailVerifyPending: selectEmailVerifyIsPending(state),
fetching: selectFetchingRewards(state), fetching: selectFetchingRewards(state),
rewards: selectUnclaimedRewards(state), rewards: selectUnclaimedRewards(state),
claimed: selectClaimedRewards(state),
user: selectUser(state), user: selectUser(state),
}); });

View file

@ -8,10 +8,9 @@ import {
View View
} from 'react-native'; } from 'react-native';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants';
import Link from 'component/link'; import Link from 'component/link';
import CustomRewardCard from 'component/customRewardCard'; import CustomRewardCard from 'component/customRewardCard';
import PhoneNumberRewardSubcard from 'component/phoneNumberRewardSubcard';
import EmailRewardSubcard from 'component/emailRewardSubcard';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import RewardCard from 'component/rewardCard'; import RewardCard from 'component/rewardCard';
import RewardEnrolment from 'component/rewardEnrolment'; import RewardEnrolment from 'component/rewardEnrolment';
@ -31,7 +30,20 @@ class RewardsPage extends React.PureComponent {
scrollView = null; scrollView = null;
componentDidMount() { didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { fetchRewards, pushDrawerStack, navigation, setPlayerVisible, user } = this.props; const { fetchRewards, pushDrawerStack, navigation, setPlayerVisible, user } = this.props;
pushDrawerStack(); pushDrawerStack();
@ -45,9 +57,18 @@ class RewardsPage extends React.PureComponent {
}); });
} }
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const { emailVerifyErrorMessage, emailVerifyPending, rewards, user } = nextProps; const { currentRoute, emailVerifyErrorMessage, emailVerifyPending, rewards, user } = nextProps;
const { claimReward } = this.props; const { claimReward, currentRoute: prevRoute } = this.props;
if (Constants.DRAWER_ROUTE_REWARDS === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
if (emailVerifyPending) { if (emailVerifyPending) {
this.setState({ verifyRequestStarted: true }); this.setState({ verifyRequestStarted: true });
} }

View file

@ -9,10 +9,12 @@ import {
selectSearchUrisByQuery selectSearchUrisByQuery
} from 'lbry-redux'; } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import SearchPage from './view'; import SearchPage from './view';
const select = (state) => ({ const select = (state) => ({
currentRoute: selectCurrentRoute(state),
isSearching: selectIsSearching(state), isSearching: selectIsSearching(state),
query: selectSearchValue(state), query: selectSearchValue(state),
uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, 25)(state))(state), uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, 25)(state))(state),

View file

@ -10,6 +10,7 @@ import {
} from 'react-native'; } from 'react-native';
import { navigateToUri } from 'utils/helper'; import { navigateToUri } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import FileListItem from 'component/fileListItem'; import FileListItem from 'component/fileListItem';
import FloatingWalletBalance from 'component/floatingWalletBalance'; import FloatingWalletBalance from 'component/floatingWalletBalance';
@ -18,31 +19,71 @@ import searchStyle from 'styles/search';
class SearchPage extends React.PureComponent { class SearchPage extends React.PureComponent {
state = { state = {
currentUri: null currentQuery: null,
currentUri: null,
} }
static navigationOptions = { static navigationOptions = {
title: 'Search Results' title: 'Search Results'
}; };
didFocusListener;
componentWillMount() { componentWillMount() {
const { pushDrawerStack, setPlayerVisible } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible, query, search } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
const searchQuery = query || this.getSearchQuery();
if (searchQuery && searchQuery.trim().length > 0) {
this.setState({
currentQuery: searchQuery,
currentUri: (isURIValid(searchQuery)) ? normalizeURI(searchQuery) : null
});
search(searchQuery);
}
} }
componentDidMount() { componentDidMount() {
const { navigation, search } = this.props; this.onComponentFocused();
let searchQuery; }
if (navigation && navigation.state) {
searchQuery = navigation.state.params.searchQuery; componentWillReceiveProps(nextProps) {
const { currentRoute, query } = nextProps;
const { currentRoute: prevRoute, search } = this.props;
if (Constants.DRAWER_ROUTE_SEARCH === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
} }
if (searchQuery && searchQuery.trim().length > 0) {
this.setState({ currentUri: (isURIValid(searchQuery)) ? normalizeURI(searchQuery) : null }) if (query && query.trim().length > 0 && query !== this.state.currentQuery) {
search(searchQuery); this.setState({
currentQuery: query,
currentUri: (isURIValid(query)) ? normalizeURI(query) : null
});
search(query);
} }
} }
getSearchQuery() {
const { navigation } = this.props;
if (navigation && navigation.state && navigation.state.params) {
return navigation.state.params.searchQuery;
}
return null;
}
handleSearchSubmitted = (keywords) => { handleSearchSubmitted = (keywords) => {
const { search } = this.props; const { search } = this.props;
this.setState({ currentUri: (isURIValid(keywords)) ? normalizeURI(keywords) : null }); this.setState({ currentUri: (isURIValid(keywords)) ? normalizeURI(keywords) : null });
@ -51,13 +92,13 @@ class SearchPage extends React.PureComponent {
render() { render() {
const { isSearching, navigation, query, uris, urisByQuery } = this.props; const { isSearching, navigation, query, uris, urisByQuery } = this.props;
const { searchQuery } = navigation.state.params;
return ( return (
<View style={searchStyle.container}> <View style={searchStyle.container}>
<UriBar value={searchQuery} <UriBar value={query}
navigation={navigation} navigation={navigation}
onSearchSubmitted={this.handleSearchSubmitted} /> onSearchSubmitted={this.handleSearchSubmitted}
searchView={true} />
{isSearching && {isSearching &&
<View style={searchStyle.busyContainer}> <View style={searchStyle.busyContainer}>
<ActivityIndicator size="large" color={Colors.LbryGreen} style={searchStyle.loading} /> <ActivityIndicator size="large" color={Colors.LbryGreen} style={searchStyle.loading} />

View file

@ -2,13 +2,14 @@ import { connect } from 'react-redux';
import { SETTINGS } from 'lbry-redux'; import { SETTINGS } from 'lbry-redux';
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { selectDrawerStack } from 'redux/selectors/drawer'; import { selectCurrentRoute, selectDrawerStack } from 'redux/selectors/drawer';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import Constants from 'constants'; import Constants from 'constants';
import SettingsPage from './view'; import SettingsPage from './view';
const select = state => ({ const select = state => ({
backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state), backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state),
currentRoute: selectCurrentRoute(state),
drawerStack: selectDrawerStack(state), drawerStack: selectDrawerStack(state),
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state), keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state), showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),

View file

@ -2,6 +2,7 @@ import React from 'react';
import { SETTINGS } from 'lbry-redux'; import { SETTINGS } from 'lbry-redux';
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native'; import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
import { navigateBack } from 'utils/helper'; import { navigateBack } from 'utils/helper';
import Constants from 'constants';
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
import settingsStyle from 'styles/settings'; import settingsStyle from 'styles/settings';
@ -10,12 +11,37 @@ class SettingsPage extends React.PureComponent {
title: 'Settings' title: 'Settings'
} }
componentDidMount() { didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible } = this.props; const { pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
} }
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.DRAWER_ROUTE_SETTINGS === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
render() { render() {
const { const {
backgroundPlayEnabled, backgroundPlayEnabled,

View file

@ -12,6 +12,7 @@ import {
import { NavigationActions, StackActions } from 'react-navigation'; import { NavigationActions, StackActions } from 'react-navigation';
import { decode as atob } from 'base-64'; import { decode as atob } from 'base-64';
import { navigateToUri } from 'utils/helper'; import { navigateToUri } from 'utils/helper';
import moment from 'moment';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
@ -44,19 +45,6 @@ class SplashScreen extends React.PureComponent {
} }
} }
componentDidMount() {
// Start measuring the first launch time from the splash screen (time from daemon start to user interaction)
AsyncStorage.getItem('hasLaunched').then(value => {
if (value == null || value !== 'true') {
AsyncStorage.setItem('hasLaunched', 'true');
// only set firstLaunchTime since we've determined that this is the first app launch ever
AsyncStorage.setItem('firstLaunchTime', String(moment().unix()));
}
});
this.props.fetchRewardedContent();
}
updateStatus() { updateStatus() {
Lbry.status().then(status => { Lbry.status().then(status => {
this._updateStatusCallback(status); this._updateStatusCallback(status);
@ -246,12 +234,22 @@ class SplashScreen extends React.PureComponent {
NativeModules.Firebase.track('app_launch', null); NativeModules.Firebase.track('app_launch', null);
} }
this.props.fetchRewardedContent();
Linking.getInitialURL().then((url) => { Linking.getInitialURL().then((url) => {
if (url) { if (url) {
this.setState({ launchUrl: url }); this.setState({ launchUrl: url });
} }
}); });
// Start measuring the first launch time from the splash screen (time from daemon start to user interaction)
AsyncStorage.getItem('hasLaunched').then(value => {
if (value == null || value !== 'true') {
AsyncStorage.setItem('hasLaunched', 'true');
// only set firstLaunchTime since we've determined that this is the first app launch ever
AsyncStorage.setItem('firstLaunchTime', String(moment().unix()));
}
});
Lbry Lbry
.connect() .connect()
.then(() => { .then(() => {

View file

@ -15,10 +15,12 @@ import {
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import SubscriptionsPage from './view'; import SubscriptionsPage from './view';
const select = state => ({ const select = state => ({
currentRoute: selectCurrentRoute(state),
loading: loading:
selectIsFetchingSubscriptions(state) || selectIsFetchingSubscriptions(state) ||
Boolean(Object.keys(selectSubscriptionsBeingFetched(state)).length), Boolean(Object.keys(selectSubscriptionsBeingFetched(state)).length),

View file

@ -29,23 +29,46 @@ class SubscriptionsPage extends React.PureComponent {
showingSuggestedSubs: false showingSuggestedSubs: false
}; };
didFocusListener;
componentWillMount() { componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { const {
doFetchMySubscriptions, doFetchMySubscriptions,
doFetchRecommendedSubscriptions, doFetchRecommendedSubscriptions,
doSetViewMode,
pushDrawerStack, pushDrawerStack,
setPlayerVisible setPlayerVisible,
subscriptionsViewMode
} = this.props; } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
doFetchMySubscriptions(); doFetchMySubscriptions();
doFetchRecommendedSubscriptions(); doFetchRecommendedSubscriptions();
doSetViewMode(subscriptionsViewMode ? subscriptionsViewMode : Constants.SUBSCRIPTIONS_VIEW_ALL);
} }
componentDidMount() { componentDidMount() {
const { doSetViewMode, subscriptionsViewMode } = this.props; this.onComponentFocused();
doSetViewMode(subscriptionsViewMode ? subscriptionsViewMode : Constants.SUBSCRIPTIONS_VIEW_ALL); }
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.FULL_ROUTE_NAME_MY_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
} }
changeViewMode = (viewMode) => { changeViewMode = (viewMode) => {

View file

@ -5,10 +5,12 @@ import {
selectIsFetchingTransactions, selectIsFetchingTransactions,
} from 'lbry-redux'; } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import TransactionHistoryPage from './view'; import TransactionHistoryPage from './view';
const select = state => ({ const select = state => ({
currentRoute: selectCurrentRoute(state),
fetchingTransactions: selectIsFetchingTransactions(state), fetchingTransactions: selectIsFetchingTransactions(state),
transactions: selectTransactionItems(state), transactions: selectTransactionItems(state),
}); });

View file

@ -5,14 +5,36 @@ import UriBar from 'component/uriBar';
import walletStyle from 'styles/wallet'; import walletStyle from 'styles/wallet';
class TransactionHistoryPage extends React.PureComponent { class TransactionHistoryPage extends React.PureComponent {
didFocusListener;
componentWillMount() { componentWillMount() {
const { pushDrawerStack, setPlayerVisible } = this.props; const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { fetchTransactions, pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
fetchTransactions();
} }
componentDidMount() { componentDidMount() {
this.props.fetchTransactions(); this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.DRAWER_ROUTE_TRANSACTION_HISTORY === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
} }
render() { render() {

View file

@ -1,10 +1,12 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doFetchTrendingUris, selectTrendingUris, selectFetchingTrendingUris } from 'lbryinc'; import { doFetchTrendingUris, selectTrendingUris, selectFetchingTrendingUris } from 'lbryinc';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; import Constants from 'constants';
import TrendingPage from './view'; import TrendingPage from './view';
const select = state => ({ const select = state => ({
currentRoute: selectCurrentRoute(state),
trendingUris: selectTrendingUris(state), trendingUris: selectTrendingUris(state),
fetchingTrendingUris: selectFetchingTrendingUris(state), fetchingTrendingUris: selectFetchingTrendingUris(state),
}); });

View file

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import NavigationActions from 'react-navigation';
import { import {
ActivityIndicator, ActivityIndicator,
NativeModules, NativeModules,
@ -14,17 +13,43 @@ import FileItem from 'component/fileItem';
import discoverStyle from 'styles/discover'; import discoverStyle from 'styles/discover';
import fileListStyle from 'styles/fileList'; import fileListStyle from 'styles/fileList';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants';
import FloatingWalletBalance from 'component/floatingWalletBalance'; import FloatingWalletBalance from 'component/floatingWalletBalance';
import UriBar from 'component/uriBar'; import UriBar from 'component/uriBar';
class TrendingPage extends React.PureComponent { class TrendingPage extends React.PureComponent {
componentDidMount() { didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
onComponentFocused = () => {
const { fetchTrendingUris, pushDrawerStack, setPlayerVisible } = this.props; const { fetchTrendingUris, pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
fetchTrendingUris(); fetchTrendingUris();
} }
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.FULL_ROUTE_NAME_TRENDING === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
render() { render() {
const { trendingUris, fetchingTrendingUris, navigation } = this.props; const { trendingUris, fetchingTrendingUris, navigation } = this.props;
const hasContent = typeof trendingUris === 'object' && trendingUris.length, const hasContent = typeof trendingUris === 'object' && trendingUris.length,

View file

@ -121,6 +121,7 @@ class EmailVerifyPage extends React.PureComponent {
<TextInput style={firstRunStyle.emailInput} <TextInput style={firstRunStyle.emailInput}
placeholder={this.state.placeholder} placeholder={this.state.placeholder}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
selectionColor={Colors.NextLbryGreen}
value={this.state.email} value={this.state.email}
onChangeText={text => this.handleChangeText(text)} onChangeText={text => this.handleChangeText(text)}
onFocus={() => { onFocus={() => {

View file

@ -192,6 +192,7 @@ class PhoneVerifyPage extends React.PureComponent {
keyboardType="numeric" keyboardType="numeric"
placeholder="0000" placeholder="0000"
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
selectionColor={Colors.NextLbryGreen}
value={this.state.verificationCode} value={this.state.verificationCode}
onChangeText={text => this.handleChangeText(text)} onChangeText={text => this.handleChangeText(text)}
/> />

View file

@ -6,6 +6,7 @@ import {
NativeModules, NativeModules,
Text, Text,
TextInput, TextInput,
TouchableOpacity,
View View
} from 'react-native'; } from 'react-native';
import { BarPasswordStrengthDisplay } from 'react-native-password-strength-meter'; import { BarPasswordStrengthDisplay } from 'react-native-password-strength-meter';
@ -14,6 +15,7 @@ import Link from 'component/link';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; import Constants from 'constants';
import firstRunStyle from 'styles/firstRun'; import firstRunStyle from 'styles/firstRun';
import Icon from 'react-native-vector-icons/FontAwesome5';
import rewardStyle from 'styles/reward'; import rewardStyle from 'styles/reward';
@ -24,6 +26,7 @@ class SyncVerifyPage extends React.PureComponent {
placeholder: 'password', placeholder: 'password',
syncApplyStarted: false, syncApplyStarted: false,
syncChecked: false, syncChecked: false,
revealPassword: false
} }
componentDidMount() { componentDidMount() {
@ -117,23 +120,31 @@ class SyncVerifyPage extends React.PureComponent {
<View> <View>
<Text style={rewardStyle.verificationTitle}>Wallet Sync</Text> <Text style={rewardStyle.verificationTitle}>Wallet Sync</Text>
{paragraph} {paragraph}
<TextInput style={firstRunStyle.passwordInput} <View style={firstRunStyle.passwordInputContainer}>
placeholder={this.state.placeholder} <TextInput style={firstRunStyle.passwordInput}
underlineColorAndroid="transparent" placeholder={this.state.placeholder}
secureTextEntry={true} underlineColorAndroid="transparent"
value={this.state.password} selectionColor={Colors.NextLbryGreen}
onChangeText={text => this.handleChangeText(text)} secureTextEntry={!this.state.revealPassword}
onFocus={() => { value={this.state.password}
if (!this.state.password || this.state.password.length === 0) { onChangeText={text => this.handleChangeText(text)}
this.setState({ placeholder: '' }); onFocus={() => {
} if (!this.state.password || this.state.password.length === 0) {
}} this.setState({ placeholder: '' });
onBlur={() => { }
if (!this.state.password || this.state.password.length === 0) { }}
this.setState({ placeholder: 'password' }); onBlur={() => {
} if (!this.state.password || this.state.password.length === 0) {
}} this.setState({ placeholder: 'password' });
/> }
}}
/>
<TouchableOpacity
style={firstRunStyle.revealPasswordIcon}
onPress={() => this.setState({ revealPassword: !this.state.revealPassword })}>
<Icon name={this.state.revealPassword ? "eye-slash" : "eye"} size={16} style={firstRunStyle.revealIcon} />
</TouchableOpacity>
</View>
{(!hasSyncedWallet && this.state.password && this.state.password.trim().length) > 0 && {(!hasSyncedWallet && this.state.password && this.state.password.trim().length) > 0 &&
<View style={firstRunStyle.passwordStrength}> <View style={firstRunStyle.passwordStrength}>
<BarPasswordStrengthDisplay <BarPasswordStrengthDisplay

View file

@ -61,7 +61,7 @@ class VerificationScreen extends React.PureComponent {
this.setState({ currentPage: 'syncVerify' }); this.setState({ currentPage: 'syncVerify' });
} }
} else { } else {
if (this.state.isEmailVerified && !this.state.isIdentityVerified) { if (this.state.isEmailVerified && !this.state.isIdentityVerified && !this.state.isRewardApproved) {
this.setState({ currentPage: 'phoneVerify' }); this.setState({ currentPage: 'phoneVerify' });
} }
if (this.state.isEmailVerified && this.state.isIdentityVerified && !this.state.isRewardApproved) { if (this.state.isEmailVerified && this.state.isIdentityVerified && !this.state.isRewardApproved) {
@ -74,7 +74,7 @@ class VerificationScreen extends React.PureComponent {
return; return;
} }
if (this.state.isEmailVerified && this.state.isIdentityVerified && this.state.isRewardApproved) { if (this.state.isEmailVerified && this.state.isRewardApproved) {
// verification steps already completed // verification steps already completed
// simply navigate back to the rewards page // simply navigate back to the rewards page
navigation.goBack(); navigation.goBack();

View file

@ -2,18 +2,21 @@ import { connect } from 'react-redux';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { selectCurrentRoute } from 'redux/selectors/drawer';
import { selectBalance } from 'lbry-redux'; import { selectBalance } from 'lbry-redux';
import { doCheckSync, doGetSync, selectUser, selectHasSyncedWallet } from 'lbryinc'; import { doCheckSync, doGetSync, selectUser, selectHasSyncedWallet } from 'lbryinc';
import Constants from 'constants'; import Constants from 'constants';
import WalletPage from './view'; import WalletPage from './view';
const select = state => ({ const select = state => ({
user: selectUser(state), currentRoute: selectCurrentRoute(state),
backupDismissed: makeSelectClientSetting(Constants.SETTING_BACKUP_DISMISSED)(state),
balance: selectBalance(state), balance: selectBalance(state),
hasSyncedWallet: selectHasSyncedWallet(state), hasSyncedWallet: selectHasSyncedWallet(state),
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
backupDismissed: makeSelectClientSetting(Constants.SETTING_BACKUP_DISMISSED)(state),
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state), rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
understandsRisks: makeSelectClientSetting(Constants.SETTING_ALPHA_UNDERSTANDS_RISKS)(state),
user: selectUser(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({

View file

@ -13,7 +13,32 @@ import Constants from 'constants';
import walletStyle from 'styles/wallet'; import walletStyle from 'styles/wallet';
class WalletPage extends React.PureComponent { class WalletPage extends React.PureComponent {
didFocusListener;
componentWillMount() {
const { navigation } = this.props;
this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
}
}
componentDidMount() { componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const { currentRoute } = nextProps;
const { currentRoute: prevRoute } = this.props;
if (Constants.FULL_ROUTE_NAME_WALLET === currentRoute && currentRoute !== prevRoute) {
this.onComponentFocused();
}
}
onComponentFocused = () => {
const { pushDrawerStack, setPlayerVisible } = this.props; const { pushDrawerStack, setPlayerVisible } = this.props;
pushDrawerStack(); pushDrawerStack();
setPlayerVisible(); setPlayerVisible();
@ -54,7 +79,7 @@ class WalletPage extends React.PureComponent {
</Text> </Text>
{!hasSyncedWallet && {!hasSyncedWallet &&
<Text style={walletStyle.warningParagraph}> <Text style={walletStyle.warningParagraph}>
If you are not using the LBRY sync service, you will lose all of your credits if you uninstall this application. Instructions on how to enroll as well as how to backup your wallet manually are available on the next page. Since you are not using the LBRY sync service, you will lose all of your credits if you uninstall this application. Instructions on how to enroll as well as how to backup your wallet manually are available on the next page.
</Text>} </Text>}
<Text style={walletStyle.warningText}> <Text style={walletStyle.warningText}>
If you understand the risks and you wish to continue, please tap the button below. If you understand the risks and you wish to continue, please tap the button below.

View file

@ -3,7 +3,8 @@ import Constants from 'constants';
const reducers = {}; const reducers = {};
const defaultState = { const defaultState = {
stack: [ Constants.DRAWER_ROUTE_DISCOVER ], // Discover is always the first drawer route stack: [ Constants.DRAWER_ROUTE_DISCOVER ], // Discover is always the first drawer route
playerVisible: false playerVisible: false,
currentRoute: null
}; };
reducers[Constants.ACTION_SET_PLAYER_VISIBLE] = (state, action) => reducers[Constants.ACTION_SET_PLAYER_VISIBLE] = (state, action) =>
@ -35,6 +36,30 @@ reducers[Constants.ACTION_POP_DRAWER_STACK] = (state, action) => {
} }
}; };
// TODO: The ACTION_REACT_NAVIGATION_*** reducers are a workaround for the react
// navigation event listeners (willFocus, didFocus, etc) not working with the
// react-navigation-redux-helpers package.
reducers[Constants.ACTION_REACT_NAVGIATION_RESET] = (state, action) => {
return {
...state,
currentRoute: Constants.DRAWER_ROUTE_DISCOVER // default to Discover upon reset
}
}
reducers[Constants.ACTION_REACT_NAVIGATION_NAVIGATE] = (state, action) => {
return {
...state,
currentRoute: action.routeName
}
}
reducers[Constants.ACTION_REACT_NAVIGATION_REPLACE] = (state, action) => {
return {
...state,
currentRoute: action.routeName
}
}
export default function reducer(state = defaultState, action) { export default function reducer(state = defaultState, action) {
const handler = reducers[action.type]; const handler = reducers[action.type];
if (handler) return handler(state, action); if (handler) return handler(state, action);

View file

@ -13,3 +13,5 @@ export const selectLastDrawerRoute = createSelector(selectState, state => {
return null; return null;
}); });
export const selectCurrentRoute = createSelector(selectState, state => state.currentRoute);

View file

@ -31,10 +31,11 @@ const downloadsStyle = StyleSheet.create({
paddingBottom: 16 paddingBottom: 16
}, },
noDownloadsText: { noDownloadsText: {
textAlign: 'center',
fontFamily: 'Inter-UI-Regular', fontFamily: 'Inter-UI-Regular',
fontSize: 16, fontSize: 16,
position: 'absolute' lineHeight: 24,
marginLeft: 16,
marginRight: 16
}, },
loading: { loading: {
position: 'absolute' position: 'absolute'

View file

@ -56,7 +56,8 @@ const filePageStyle = StyleSheet.create({
title: { title: {
fontFamily: 'Inter-UI-Bold', fontFamily: 'Inter-UI-Bold',
fontSize: 16, fontSize: 16,
flex: 18 flex: 18,
alignSelf: 'flex-start'
}, },
titleTouch: { titleTouch: {
flex: 1, flex: 1,
@ -105,9 +106,9 @@ const filePageStyle = StyleSheet.create({
fontFamily: 'Inter-UI-Regular', fontFamily: 'Inter-UI-Regular',
fontSize: 13, fontSize: 13,
lineHeight: 18, lineHeight: 18,
marginTop: -8,
marginLeft: 12, marginLeft: 12,
marginRight: 12, marginRight: 12
marginBottom: 16
}, },
thumbnail: { thumbnail: {
width: screenWidth, width: screenWidth,
@ -311,6 +312,7 @@ const filePageStyle = StyleSheet.create({
tagContainer: { tagContainer: {
marginLeft: 12, marginLeft: 12,
marginRight: 12, marginRight: 12,
marginTop: 16,
marginBottom: 16, marginBottom: 16,
flexDirection: 'row' flexDirection: 'row'
}, },

View file

@ -182,6 +182,22 @@ const firstRunStyle = StyleSheet.create({
nowrap: { nowrap: {
flex: 1, flex: 1,
flexWrap: 'nowrap' flexWrap: 'nowrap'
},
passwordInputContainer: {
marginLeft: 32,
marginRight: 32
},
revealPasswordIcon: {
position: 'absolute',
right: 0,
top: 6,
width: 32,
height: 32,
alignItems: 'center',
justifyContent: 'center'
},
revealIcon: {
color: Colors.White
} }
}); });

View file

@ -221,6 +221,11 @@ const walletStyle = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between' justifyContent: 'space-between'
},
syncDriverRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between'
} }
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -72,7 +72,7 @@
<activity android:name="io.lbry.browser.MainActivity" <activity android:name="io.lbry.browser.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:theme="@style/LbryAppTheme"
android:configChanges="keyboardHidden|orientation{% if args.min_sdk_version >= 13 %}|screenSize{% endif %}" android:configChanges="keyboardHidden|orientation{% if args.min_sdk_version >= 13 %}|screenSize{% endif %}"
android:screenOrientation="{{ args.orientation }}" android:screenOrientation="{{ args.orientation }}"
android:launchMode="singleInstance" android:launchMode="singleInstance"

View file

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#3F51B5</color> <color name="colorPrimary">#40B89A</color>
<color name="colorPrimaryDark">#303F9F</color> <color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FFFFFF</color> <color name="colorAccent">#FFFFFF</color>
<color name="red">#FF0000</color> <color name="red">#FF0000</color>
<color name="green">#00C000</color> <color name="green">#00C000</color>
<color name="lbrygreen">#40B89A</color>
<color name="white">#FFFFFF</color> <color name="white">#FFFFFF</color>
<color name="lbryGreen">#2F9176</color>
<color name="nextLbryGreen">#38D9A9</color>
</resources> </resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,7 +1,6 @@
<resources> <resources>
<style name="LbryAppTheme" parent="@android:style/Theme.Material.Light"> <style name="LbryAppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/lbrygreen</item> <item name="android:windowBackground">@color/lbryGreen</item>
<item name="colorControlActivated">@color/white</item> <item name="colorControlActivated">@color/nextLbryGreen</item>
<item name="colorAccent">@color/white</item>
</style> </style>
</resources> </resources>

View file

@ -160,7 +160,7 @@ public class LbrynetService extends PythonService {
// Create the notification group // Create the notification group
NotificationCompat.Builder groupBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID); NotificationCompat.Builder groupBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
groupBuilder.setContentTitle("LBRY Browser") groupBuilder.setContentTitle("LBRY Browser")
.setColor(ContextCompat.getColor(context, R.color.lbrygreen)) .setColor(ContextCompat.getColor(context, R.color.lbryGreen))
.setSmallIcon(R.drawable.ic_lbry) .setSmallIcon(R.drawable.ic_lbry)
.setPriority(NotificationCompat.PRIORITY_LOW) .setPriority(NotificationCompat.PRIORITY_LOW)
.setGroup(GROUP_SERVICE) .setGroup(GROUP_SERVICE)
@ -168,7 +168,7 @@ public class LbrynetService extends PythonService {
notificationManager.notify(SERVICE_NOTIFICATION_GROUP_ID, groupBuilder.build()); notificationManager.notify(SERVICE_NOTIFICATION_GROUP_ID, groupBuilder.build());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID); NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
Notification notification = builder.setColor(ContextCompat.getColor(context, R.color.lbrygreen)) Notification notification = builder.setColor(ContextCompat.getColor(context, R.color.lbryGreen))
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setContentTitle(serviceTitle) .setContentTitle(serviceTitle)
.setContentText(serviceDescription) .setContentText(serviceDescription)

View file

@ -59,7 +59,7 @@ public class BackgroundMediaModule extends ReactContextBaseJavaModule {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, LbrynetService.NOTIFICATION_CHANNEL_ID); NotificationCompat.Builder builder = new NotificationCompat.Builder(context, LbrynetService.NOTIFICATION_CHANNEL_ID);
builder.setColor(ContextCompat.getColor(context, R.color.lbrygreen)) builder.setColor(ContextCompat.getColor(context, R.color.lbryGreen))
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setContentTitle(title) .setContentTitle(title)
.setContentText(publisher) .setContentText(publisher)

View file

@ -239,7 +239,7 @@ public class UtilityModule extends ReactContextBaseJavaModule {
boolean hasThumbnail = false; boolean hasThumbnail = false;
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID); final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setAutoCancel(true) builder.setAutoCancel(true)
.setColor(ContextCompat.getColor(context, R.color.lbrygreen)) .setColor(ContextCompat.getColor(context, R.color.lbryGreen))
.setContentIntent(DownloadManager.getLaunchPendingIntent(uri, context)) .setContentIntent(DownloadManager.getLaunchPendingIntent(uri, context))
.setContentTitle(publisher) .setContentTitle(publisher)
.setContentText(title) .setContentText(title)