add reveal password icon and more UI tweaks (#554)
* add reveal password icon and more UI tweaks * navigation workaround. more UI updates and tweaks. * update control colours. fix search. * optimise launcher icon. file page style tweak. * optimise media player buffer values
386
app/package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
|
@ -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)
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => ({
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 => ({
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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 })}>
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
|
@ -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)}
|
||||
/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 => ({
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -13,3 +13,5 @@ export const selectLastDrawerRoute = createSelector(selectState, state => {
|
|||
|
||||
return null;
|
||||
});
|
||||
|
||||
export const selectCurrentRoute = createSelector(selectState, state => state.currentRoute);
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -221,6 +221,11 @@ const walletStyle = StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
syncDriverRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
|
@ -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"
|
||||
|
|
|
@ -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>
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 11 KiB |
|
@ -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>
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|