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

View file

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

View file

@ -15,15 +15,14 @@ import VerificationScreen from 'page/verification';
import WalletPage from 'page/wallet';
import SearchInput from 'component/searchInput';
import {
createAppContainer,
createDrawerNavigator,
createStackNavigator,
NavigationActions
} from 'react-navigation';
import {
addListener,
createReduxContainer,
createReactNavigationReduxMiddleware,
createNavigationReducer
} from 'react-navigation-redux-helpers';
import { connect } from 'react-redux';
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({
Wallet: {
screen: WalletPage,
@ -165,19 +124,19 @@ const drawer = createDrawerNavigator({
DiscoverStack: { screen: discoverStack, navigationOptions: {
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 }} />
}},
MySubscriptionsStack: { screen: mySubscriptionsStack, navigationOptions: {
MySubscriptionsStack: { screen: SubscriptionsPage, navigationOptions: {
title: 'Subscriptions', drawerIcon: ({ tintColor }) => <Icon name="heart" solid={true} size={20} style={{ color: tintColor }} />
}},
WalletStack: { screen: walletStack, navigationOptions: {
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 }} />
}},
MyLBRYStack: { screen: myLbryStack, navigationOptions: {
MyLBRYStack: { screen: DownloadsPage, navigationOptions: {
title: 'Library', drawerIcon: ({ tintColor }) => <Icon name="download" size={20} style={{ color: tintColor }} />
}},
Settings: { screen: SettingsPage, navigationOptions: {
@ -225,10 +184,12 @@ const mainStackNavigator = new createStackNavigator({
export const AppNavigator = mainStackNavigator;
export const navigatorReducer = createNavigationReducer(AppNavigator);
export const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
state => state.nav,
);
const App = createReduxContainer(mainStackNavigator, "root");
const App = createReduxContainer(mainStackNavigator);
const appMapStateToProps = (state) => ({
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 (
<View style={styles} onLayout={onLayout}>
<Video source={{
uri: source,
headers: {
"Save-Data": "on",
"Accept": "*/*"
}
}}
bufferConfig={{ minBufferMs: 3000, maxBufferMs: 60000, bufferForPlaybackMs: 3000, bufferForPlaybackAfterRebufferMs: 3000 }}
<Video source={{ uri: source }}
bufferConfig={{ minBufferMs: 15000, maxBufferMs: 60000, bufferForPlaybackMs: 5000, bufferForPlaybackAfterRebufferMs: 5000 }}
ref={(ref: Video) => { this.video = ref; }}
resizeMode={this.state.resizeMode}
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,5 +1,10 @@
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';
const select = state => {
@ -7,6 +12,7 @@ const select = state => {
return {
...searchState,
query: selectSearchValue(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() {
const { navigation, onSearchSubmitted, suggestions, updateSearchQuery, value } = this.props;
if (this.state.currentValue === null) {
const { navigation, suggestions, query, searchView, value } = this.props;
if (value && this.state.currentValue === null) {
this.setState({ currentValue: value });
}
@ -127,7 +150,7 @@ class UriBar extends React.PureComponent {
underlineColorAndroid={'transparent'}
numberOfLines={1}
clearButtonMode={'while-editing'}
value={this.state.currentValue}
value={searchView ? query : this.state.currentValue}
returnKeyType={'go'}
inlineImageLeft={'baseline_search_black_24'}
inlineImagePadding={16}
@ -137,26 +160,7 @@ class UriBar extends React.PureComponent {
this.setSelection();
}}
onChangeText={this.handleChangeText}
onSubmitEditing={() => {
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 }});
}
}
}}/>
onSubmitEditing={this.handleSubmitEditing}/>
{(this.state.focused && !this.state.directSearch) && (
<View style={uriBarStyle.suggestions}>
<FlatList style={uriBarStyle.suggestionList}

View file

@ -15,7 +15,11 @@ class WalletSyncDriver extends React.PureComponent<Props> {
return (
<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 &&
<View style={walletStyle.actionRow}>
<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_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_SETTINGS: "settings",
PAGE_TRENDING: "trending",
@ -50,10 +54,18 @@ const Constants = {
DRAWER_ROUTE_SEARCH: "Search",
DRAWER_ROUTE_TRANSACTION_HISTORY: "TransactionHistory",
SUBSCRIPTIONS_VIEW_ALL: 'view_all',
SUBSCRIPTIONS_VIEW_LATEST_FIRST: 'view_latest_first',
FULL_ROUTE_NAME_DISCOVER: "DiscoverStack",
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)
};

View file

@ -28,9 +28,8 @@ import {
userReducer
} from 'lbryinc';
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 AppWithNavigationState, { reactNavigationMiddleware } from './component/AppNavigator';
import AsyncStorage from '@react-native-community/async-storage';
import FilesystemStorage from 'redux-persist-filesystem-storage';
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 initialNavState = router.getStateForAction(navAction);
const navigatorReducer = (state = initialNavState, action) => {
const nextState = AppNavigator.router.getStateForAction(action, state);
return nextState || state;
};
const initialNavState = router.getStateForAction(navAction);*/
const reducers = combineReducers({
auth: authReducer,

View file

@ -2,14 +2,15 @@ import { connect } from 'react-redux';
import { doToast } from 'lbry-redux';
import { doFetchAccessToken, selectAccessToken, selectUserEmail } from 'lbryinc';
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 Constants from 'constants';
const select = state => ({
accessToken: selectAccessToken(state),
userEmail: selectUserEmail(state),
currentRoute: selectCurrentRoute(state),
drawerStack: selectDrawerStack(state),
userEmail: selectUserEmail(state),
});
const perform = dispatch => ({

View file

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

View file

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

View file

@ -11,6 +11,7 @@ import {
} from 'react-native';
import { navigateToUri, uriFromFileInfo } from 'utils/helper';
import Colors from 'styles/colors';
import Constants from 'constants';
import PageHeader from 'component/pageHeader';
import FileListItem from 'component/fileListItem';
import FloatingWalletBalance from 'component/floatingWalletBalance';
@ -24,13 +25,38 @@ class DownloadsPage extends React.PureComponent {
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;
pushDrawerStack();
setPlayerVisible();
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() {
const { fetching, fileInfos, navigation } = this.props;
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
@ -60,14 +86,8 @@ class DownloadsPage extends React.PureComponent {
onPress={() => navigateToUri(navigation, uriFromFileInfo(item), { autoplay: true })} />
)
}
data={fileInfos.sort((a, b) => {
// TODO: Implement sort based on user selection
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}
data={fileInfos}
keyExtractor={(item, index) => item.outpoint}
/>
</View>}
<FloatingWalletBalance navigation={navigation} />

View file

@ -22,8 +22,9 @@ import { navigateBack, navigateToUri } from 'utils/helper';
import Icon from 'react-native-vector-icons/FontAwesome5';
import ImageViewer from 'react-native-image-zoom-viewer';
import Button from 'component/button';
import Colors from 'styles/colors';
import ChannelPage from 'page/channel';
import Colors from 'styles/colors';
import Constants from 'constants';
import DateTime from 'component/dateTime';
import FileDownloadButton from 'component/fileDownloadButton';
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);
DeviceEventEmitter.addListener('onDownloadStarted', this.handleDownloadStarted);
@ -105,9 +113,14 @@ class FilePage extends React.PureComponent {
}
}
componentDidMount() {
this.onComponentFocused();
}
componentWillReceiveProps(nextProps) {
const {
claim,
currentRoute,
failedPurchaseUris: prevFailedPurchaseUris,
purchasedUris: prevPurchasedUris,
navigation,
@ -115,7 +128,18 @@ class FilePage extends React.PureComponent {
notify
} = this.props;
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 (purchaseUriErrorMessage && purchaseUriErrorMessage.trim().length > 0) {
@ -131,6 +155,10 @@ class FilePage extends React.PureComponent {
const { nout, txid } = claim;
const outpoint = `${txid}:${nout}`;
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();
}
@ -160,16 +188,6 @@ class FilePage extends React.PureComponent {
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) {
@ -276,6 +294,9 @@ class FilePage extends React.PureComponent {
utility.keepAwakeOff();
utility.showNavigationBar();
}
if (this.didFocusListener) {
this.didFocusListener.remove();
}
if (window.currentMediaInfo) {
window.currentMediaInfo = null;
}
@ -313,6 +334,9 @@ class FilePage extends React.PureComponent {
playerUriForFileInfo = (fileInfo) => {
const { streamingUrl } = this.props;
if (fileInfo && fileInfo.download_path) {
return this.getEncodedDownloadPath(fileInfo);
}
if (streamingUrl) {
return streamingUrl;
}
@ -320,10 +344,6 @@ class FilePage extends React.PureComponent {
return this.state.currentStreamUrl;
}
if (fileInfo && fileInfo.download_path) {
return this.getEncodedDownloadPath(fileInfo);
}
return null;
}
@ -402,9 +422,9 @@ class FilePage extends React.PureComponent {
this.startTime = null;
}
const { fileInfo, navigation } = this.props;
const { claim, navigation } = this.props;
const { uri } = navigation.state.params;
this.logFileView(uri, fileInfo, timeToStartMillis);
this.logFileView(uri, claim, timeToStartMillis);
let payload = { 'uri': uri };
if (!isNaN(timeToStart)) {
@ -560,7 +580,8 @@ class FilePage extends React.PureComponent {
const isPlayable = mediaType === 'video' || mediaType === 'audio';
const { height, channel_name: channelName, value } = claim;
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 canSendTip = this.state.tipAmount > 0;
const fullChannelUri = channelClaimId && channelClaimId.trim().length > 0 ? `${channelName}#${channelClaimId}` : channelName;
@ -703,6 +724,7 @@ class FilePage extends React.PureComponent {
<ScrollView
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
contentContainerstyle={showActions ? null : filePageStyle.scrollContent}
keyboardShouldPersistTaps={'handled'}
ref={(ref) => { this.scrollView = ref; }}>
<TouchableWithoutFeedback style={filePageStyle.titleTouch}
onPress={() => this.setState({ showDescription: !this.state.showDescription })}>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@ import {
} from 'react-native';
import { navigateToUri } from 'utils/helper';
import Colors from 'styles/colors';
import Constants from 'constants';
import PageHeader from 'component/pageHeader';
import FileListItem from 'component/fileListItem';
import FloatingWalletBalance from 'component/floatingWalletBalance';
@ -18,31 +19,71 @@ import searchStyle from 'styles/search';
class SearchPage extends React.PureComponent {
state = {
currentUri: null
currentQuery: null,
currentUri: null,
}
static navigationOptions = {
title: 'Search Results'
};
didFocusListener;
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();
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() {
const { navigation, search } = this.props;
let searchQuery;
if (navigation && navigation.state) {
searchQuery = navigation.state.params.searchQuery;
this.onComponentFocused();
}
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 })
search(searchQuery);
if (query && query.trim().length > 0 && query !== this.state.currentQuery) {
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) => {
const { search } = this.props;
this.setState({ currentUri: (isURIValid(keywords)) ? normalizeURI(keywords) : null });
@ -51,13 +92,13 @@ class SearchPage extends React.PureComponent {
render() {
const { isSearching, navigation, query, uris, urisByQuery } = this.props;
const { searchQuery } = navigation.state.params;
return (
<View style={searchStyle.container}>
<UriBar value={searchQuery}
<UriBar value={query}
navigation={navigation}
onSearchSubmitted={this.handleSearchSubmitted} />
onSearchSubmitted={this.handleSearchSubmitted}
searchView={true} />
{isSearching &&
<View style={searchStyle.busyContainer}>
<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 { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
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 Constants from 'constants';
import SettingsPage from './view';
const select = state => ({
backgroundPlayEnabled: makeSelectClientSetting(SETTINGS.BACKGROUND_PLAY_ENABLED)(state),
currentRoute: selectCurrentRoute(state),
drawerStack: selectDrawerStack(state),
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),

View file

@ -2,6 +2,7 @@ import React from 'react';
import { SETTINGS } from 'lbry-redux';
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
import { navigateBack } from 'utils/helper';
import Constants from 'constants';
import PageHeader from 'component/pageHeader';
import settingsStyle from 'styles/settings';
@ -10,12 +11,37 @@ class SettingsPage extends React.PureComponent {
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;
pushDrawerStack();
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() {
const {
backgroundPlayEnabled,

View file

@ -12,6 +12,7 @@ import {
import { NavigationActions, StackActions } from 'react-navigation';
import { decode as atob } from 'base-64';
import { navigateToUri } from 'utils/helper';
import moment from 'moment';
import AsyncStorage from '@react-native-community/async-storage';
import PropTypes from 'prop-types';
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() {
Lbry.status().then(status => {
this._updateStatusCallback(status);
@ -246,12 +234,22 @@ class SplashScreen extends React.PureComponent {
NativeModules.Firebase.track('app_launch', null);
}
this.props.fetchRewardedContent();
Linking.getInitialURL().then((url) => {
if (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
.connect()
.then(() => {

View file

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

View file

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

View file

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

View file

@ -5,14 +5,36 @@ import UriBar from 'component/uriBar';
import walletStyle from 'styles/wallet';
class TransactionHistoryPage extends React.PureComponent {
didFocusListener;
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();
setPlayerVisible();
fetchTransactions();
}
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() {

View file

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

View file

@ -1,5 +1,4 @@
import React from 'react';
import NavigationActions from 'react-navigation';
import {
ActivityIndicator,
NativeModules,
@ -14,17 +13,43 @@ import FileItem from 'component/fileItem';
import discoverStyle from 'styles/discover';
import fileListStyle from 'styles/fileList';
import Colors from 'styles/colors';
import Constants from 'constants';
import FloatingWalletBalance from 'component/floatingWalletBalance';
import UriBar from 'component/uriBar';
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;
pushDrawerStack();
setPlayerVisible();
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() {
const { trendingUris, fetchingTrendingUris, navigation } = this.props;
const hasContent = typeof trendingUris === 'object' && trendingUris.length,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,7 +13,32 @@ import Constants from 'constants';
import walletStyle from 'styles/wallet';
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() {
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;
pushDrawerStack();
setPlayerVisible();
@ -54,7 +79,7 @@ class WalletPage extends React.PureComponent {
</Text>
{!hasSyncedWallet &&
<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 style={walletStyle.warningText}>
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 defaultState = {
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) =>
@ -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) {
const handler = reducers[action.type];
if (handler) return handler(state, action);

View file

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

View file

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

View file

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

View file

@ -182,6 +182,22 @@ const firstRunStyle = StyleSheet.create({
nowrap: {
flex: 1,
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',
alignItems: 'center',
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"
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:screenOrientation="{{ args.orientation }}"
android:launchMode="singleInstance"

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

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

View file

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

View file

@ -59,7 +59,7 @@ public class BackgroundMediaModule extends ReactContextBaseJavaModule {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
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)
.setContentTitle(title)
.setContentText(publisher)

View file

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