diff --git a/package-lock.json b/package-lock.json index 1b5a135c0..5052e5116 100644 --- a/package-lock.json +++ b/package-lock.json @@ -881,12 +881,12 @@ }, "dependencies": { "browserslist": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.7.tgz", - "integrity": "sha512-oYVLxFVqpX9uMhOIQBLtZL+CX4uY8ZpWcjNTaxyWl5rO8yA9SSNikFnAfvk8J3P/7z3BZwNmEqFKaJoYltj3MQ==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "requires": { - "caniuse-lite": "^1.0.30000835", - "electron-to-chromium": "^1.3.45" + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" } } } @@ -1983,9 +1983,9 @@ } }, "@types/node": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.1.tgz", - "integrity": "sha512-n7wxy8r2tjVcrzZoKJlyZmi1C1VhXGHAGhDEO1iqp7fbsTSsDF3dVA50KFsPg77EXqzNJqbzcna8Mi4m7a1lyw==" + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.2.tgz", + "integrity": "sha512-bjk1RIeZBCe/WukrFToIVegOf91Pebr8cXYBwLBIsfiGWVQ+ifwWsT59H3RxrWzWrzd1l/Amk1/ioY5Fq3/bpA==" }, "abab": { "version": "1.0.4", @@ -2066,14 +2066,15 @@ } }, "airbnb-js-shims": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-1.4.1.tgz", - "integrity": "sha512-b7S3d+DPRMwaDAs0cgKQTMLO/JG/iSehIlzEGvt2FpxIztRDDABEjWI73AfTxkSiK3/OsraPRYxVNAX3yhSNLw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-1.5.1.tgz", + "integrity": "sha512-Dqk+NEHgxuHNAt5FWKmwWsR9Q1dRonVzWTmDs1fhX1L/Rwi8R0ZYzrPHsCveg/AnrKM64RlAkXOiYnEtbWZcXA==", "dev": true, "requires": { "array-includes": "^3.0.3", - "array.prototype.flatmap": "^1.2.0", - "array.prototype.flatten": "^1.2.0", + "array.prototype.flat": "^1.2.1", + "array.prototype.flatmap": "^1.2.1", + "array.prototype.flatten": "^1.2.1", "es5-shim": "^4.5.10", "es6-shim": "^0.35.3", "function.prototype.name": "^1.1.0", @@ -2082,7 +2083,8 @@ "object.values": "^1.0.4", "promise.prototype.finally": "^3.1.0", "string.prototype.padend": "^3.0.0", - "string.prototype.padstart": "^3.0.0" + "string.prototype.padstart": "^3.0.0", + "symbol.prototype.description": "^1.0.0" } }, "ajv": { @@ -2363,6 +2365,17 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "array.prototype.flat": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", + "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1" + } + }, "array.prototype.flatmap": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.1.tgz", @@ -2440,11 +2453,11 @@ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=" }, "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "^4.14.0" + "lodash": "^4.17.10" } }, "async-each": { @@ -4103,14 +4116,6 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.x.x" - } - }, "bowser": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.3.tgz", @@ -4464,14 +4469,14 @@ } }, "caniuse-db": { - "version": "1.0.30000843", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000843.tgz", - "integrity": "sha1-T36FAfVX3JvNN90zrIWQXHZe/sI=" + "version": "1.0.30000844", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000844.tgz", + "integrity": "sha1-vKV5jNoraTHWgQDC1p5V+zOMu0E=" }, "caniuse-lite": { - "version": "1.0.30000843", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000843.tgz", - "integrity": "sha512-1ntiW826MhRBmM0CeI7w1cQr16gxwOoM8doJWh3BFalPZoKWdZXs27Bc04xth/3NR1/wNXn9cpP4F92lVenCvg==" + "version": "1.0.30000844", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000844.tgz", + "integrity": "sha512-UpKQE7y6dLHhlv75UyBCRiun34Q+bmxyX3zS+ve9M07YG52tRafOvop9N9d5jC+sikKuG7UMweJKJNts4FVehA==" }, "capture-stack-trace": { "version": "1.0.0", @@ -5069,24 +5074,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.x.x" - } - } - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -5853,9 +5840,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.47", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.47.tgz", - "integrity": "sha1-dk6IfKkQTQGgrI6r7n38DizhQQQ=" + "version": "1.3.48", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", + "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=" }, "elliptic": { "version": "6.4.0", @@ -7142,9 +7129,9 @@ } }, "follow-redirects": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", - "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", "requires": { "debug": "^3.1.0" }, @@ -8240,17 +8227,6 @@ "minimalistic-assert": "^1.0.0" } }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } - }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -8278,11 +8254,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, "hoist-non-react-statics": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz", @@ -8359,9 +8330,9 @@ } }, "html-minifier": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.15.tgz", - "integrity": "sha512-OZa4rfb6tZOZ3Z8Xf0jKxXkiDcFWldQePGYFDcgKqES2sXeWaEv9y6QQvWUtX3ySI3feApQi5uCsHLINQ6NoAw==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.16.tgz", + "integrity": "sha512-zP5EfLSpiLRp0aAgud4CQXPQZm9kXwWjR/cF0PfdOj+jjWnOaCgeZcll4kYXSvIBPeUMmyaSc7mM4IDtA+kboA==", "requires": { "camel-case": "3.0.x", "clean-css": "4.1.x", @@ -8434,9 +8405,9 @@ } }, "http-parser-js": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.12.tgz", - "integrity": "sha1-uc+/Sizybw/DSxDKFImid3HjR08=" + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=" }, "http-proxy": { "version": "1.17.0", @@ -8830,13 +8801,6 @@ "pull-stream": "^3.6.7", "pull-traverse": "^1.0.3", "stable": "0.1.6" - }, - "dependencies": { - "stable": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz", - "integrity": "sha1-kQ9dKu17Ugxud3SZwfMuE5/eyxA=" - } } }, "is-absolute-url": { @@ -8867,6 +8831,11 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, + "is-binary": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-binary/-/is-binary-0.1.0.tgz", + "integrity": "sha1-jn0yenq5B6g4+BE+nOUWjf2786s=" + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -9118,9 +9087,9 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" }, "is-redirect": { "version": "1.0.0", @@ -10372,11 +10341,6 @@ "yallist": "^2.1.2" } }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=" - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -10915,11 +10879,6 @@ "promise": "~1.3.0" }, "dependencies": { - "is-promise": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", - "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" - }, "promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-1.3.0.tgz", @@ -12024,12 +11983,11 @@ } }, "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", "requires": { - "postcss": "^5.0.4", - "uniqid": "^4.0.0" + "postcss": "^5.0.4" }, "dependencies": { "has-flag": { @@ -13017,9 +12975,9 @@ } }, "punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "puppeteer": { "version": "1.4.0", @@ -13877,9 +13835,9 @@ } }, "redux-bundler": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/redux-bundler/-/redux-bundler-21.2.0.tgz", - "integrity": "sha512-wcpvm5JY7JvW6/ABiAmzf9/TvXAWUElOaj18zRWQELDiPrc44VoJFShNGTtvf9xungDwBuvwU4oaVxsWTdlPSA==" + "version": "21.2.1", + "resolved": "https://registry.npmjs.org/redux-bundler/-/redux-bundler-21.2.1.tgz", + "integrity": "sha512-iQtUq0vtoUfgNX0Fl7Wu4YngbQpJ+2OdVp476dPhuH+zaLqtZRc24mY3x5qaYsIMY9xaDfZLLUGu35z/YLuh3w==" }, "redux-bundler-react": { "version": "1.0.0", @@ -14080,9 +14038,9 @@ } }, "request": { - "version": "2.86.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.86.0.tgz", - "integrity": "sha512-BQZih67o9r+Ys94tcIW4S7Uu8pthjrQVxhsZ/weOwHbDfACxvIyvnAbzFQxjy1jMtvFSzv5zf4my6cZsJBbVzw==", + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.6.0", @@ -14092,7 +14050,6 @@ "forever-agent": "~0.6.1", "form-data": "~2.3.1", "har-validator": "~5.0.3", - "hawk": "~6.0.2", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -14255,6 +14212,13 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "requires": { "is-promise": "^2.1.0" + }, + "dependencies": { + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + } } }, "run-parallel": { @@ -14694,14 +14658,6 @@ } } }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.x.x" - } - }, "sockjs": { "version": "0.3.18", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", @@ -14920,9 +14876,9 @@ } }, "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz", + "integrity": "sha1-kQ9dKu17Ugxud3SZwfMuE5/eyxA=" }, "standard": { "version": "11.0.1", @@ -15591,6 +15547,15 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" }, + "symbol.prototype.description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.0.tgz", + "integrity": "sha512-I9mrbZ5M96s7QeJDv95toF1svkUjeBybe8ydhY7foPaBmr0SPJMFupArmMkDrOKTTj0sJVr+nvQNxWLziQ7nDQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, "table": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", @@ -15886,9 +15851,9 @@ "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" }, "uglify-js": { - "version": "3.3.25", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.25.tgz", - "integrity": "sha512-hobogryjDV36VrLK3Y69ou4REyrTApzUblVFmdQOYRe8cYaSmFJXMb4dR9McdvYDSbeNdzUgYr2YVukJaErJcA==", + "version": "3.3.27", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.27.tgz", + "integrity": "sha512-O94wxMSb3td/TlofkITYvYIlvIVdldvNXDVRekzK13CQZuL37ua4nrdXX0Ro7MapfUVzglRHs0/+imPRUdOghg==", "requires": { "commander": "~2.15.0", "source-map": "~0.6.1" @@ -16028,14 +15993,6 @@ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", - "requires": { - "macaddress": "^0.2.8" - } - }, "uniqs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", diff --git a/package.json b/package.json index fa955cf6d..44d00a073 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "ipfs-css": "^0.5.0", "ipld-dag-pb": "^0.14.3", "ipfs-unixfs": "^0.1.14", + "is-binary": "^0.1.0", "milliseconds": "^1.0.3", "multibase": "^0.4.0", "multicodec": "^0.2.6", diff --git a/src/App.js b/src/App.js index 1e2f4535a..833952798 100644 --- a/src/App.js +++ b/src/App.js @@ -45,4 +45,9 @@ export class App extends Component { } } -export default connect('selectRoute', 'doUpdateUrl', 'doInitIpfs', App) +export default connect( + 'selectRoute', + 'doUpdateUrl', + 'doInitIpfs', + App +) diff --git a/src/App.test.js b/src/App.test.js index 3a2927b72..4bb8ba76d 100644 --- a/src/App.test.js +++ b/src/App.test.js @@ -19,7 +19,7 @@ it('example test', async () => { let titleText = await page.evaluate(el => el.innerHTML, title) expect(titleText).toBe('Status') - await page.click('nav a[href="#/files"]') + await page.click('nav a[href="#/files/"]') title = await page.$('[data-id=title]') titleText = await page.evaluate(el => el.innerHTML, title) diff --git a/src/bundles/files.js b/src/bundles/files.js new file mode 100644 index 000000000..22db00ff8 --- /dev/null +++ b/src/bundles/files.js @@ -0,0 +1,146 @@ +import { createAsyncResourceBundle, createSelector } from 'redux-bundler' +import { join } from '../lib/path' + +const bundle = createAsyncResourceBundle({ + name: 'files', + actionBaseType: 'FILES', + getPromise: (args) => { + const {store, getIpfs} = args + let path = store.selectRouteParams().path + + if (!path) { + store.doUpdateHash('/files/') + return Promise.resolve() + } + + // FIX: dirs with actually encoded names + // will get decoded... it shouldn't happen + path = decodeURIComponent(path) + + return getIpfs().files.stat(path) + .then(stats => { + if (stats.type === 'directory') { + return getIpfs().files.ls(path, {l: true}).then((res) => { + // FIX: open PR on js-ipfs-api + if (res) { + res = res.map(file => { + file.type = file.type === 0 ? 'file' : 'directory' + return file + }) + } + + return { + path: path, + type: 'directory', + files: res + } + }) + } else { + stats.name = path + + return { + path: path, + type: 'file', + stats: stats, + read: () => getIpfs().files.read(path) + } + } + }) + }, + staleAfter: 100, + checkIfOnline: false +}) + +bundle.reactFilesFetch = createSelector( + 'selectFilesShouldUpdate', + 'selectIpfsReady', + 'selectRouteInfo', + 'selectFiles', + (shouldUpdate, ipfsReady, {url, params}, files) => { + if (shouldUpdate && ipfsReady && url.startsWith('/files')) { + if (!files || files.path !== params.path) { + return { actionCreator: 'doFetchFiles' } + } + } + } +) + +bundle.doFilesDelete = (files) => ({dispatch, getIpfs, store}) => { + dispatch({ type: 'FILES_DELETE_STARTED' }) + + const promises = files.map(file => getIpfs().files.rm(file, { recursive: true })) + Promise.all(promises) + .then(() => { + store.doFetchFiles() + dispatch({ type: 'FILES_DELETE_FINISHED' }) + }) + .catch((error) => { + dispatch({ type: 'FILES_DELETE_ERRORED', payload: error }) + }) +} + +function runAndFetch ({ dispatch, getIpfs, store }, type, action, args) { + dispatch({ type: `${type}_STARTED` }) + + return getIpfs().files[action](...args) + .then(() => { + store.doFetchFiles() + dispatch({ type: `${type}_FINISHED` }) + }) + .catch((error) => { + dispatch({ type: `${type}_ERRORED`, payload: error }) + }) +} + +bundle.doFilesRename = (from, to) => (args) => { + runAndFetch(args, 'FILES_RENAME', 'mv', [[from, to]]) +} + +bundle.doFilesCopy = (from, to) => (args) => { + runAndFetch(args, 'FILES_RENAME', 'cp', [[from, to]]) +} + +bundle.doFilesMakeDir = (path) => (args) => { + runAndFetch(args, 'FILES_MKDIR', 'mkdir', [path, { parents: true }]) +} + +function readAsBuffer (file) { + return new Promise((resolve, reject) => { + const reader = new window.FileReader() + reader.onload = (event) => { + resolve({ + content: Buffer.from(reader.result), + name: file.name + }) + } + reader.onerror = (event) => { + reject(reader.error) + } + + reader.readAsArrayBuffer(file) + }) +} + +bundle.doFilesWrite = (root, files) => ({dispatch, getIpfs, store}) => { + dispatch({ type: 'FILES_WRITE_STARTED' }) + + let promises = [] + + for (const file of files) { + promises.push(readAsBuffer(file)) + } + + return Promise.all(promises).then(files => { + return Promise.all(files.map((file) => { + const target = join(root, file.name) + return getIpfs().files.write(target, file.content, { create: true }) + })) + }).then(() => { + store.doFetchFiles() + dispatch({ type: 'FILES_WRITE_FINISHED' }) + }).catch((error) => { + dispatch({ type: 'FILES_WRITE_ERRORED', payload: error }) + }) +} + +export default bundle diff --git a/src/bundles/index.js b/src/bundles/index.js index 3c33673a5..c1b261ab6 100644 --- a/src/bundles/index.js +++ b/src/bundles/index.js @@ -6,6 +6,7 @@ import appIdle from './app-idle' import peersBundle from './peers' import routesBundle from './routes' import redirectsBundle from './redirects' +import filesBundle from './files' export default composeBundles( appIdle({idleTimeout: 5000}), @@ -13,5 +14,6 @@ export default composeBundles( objectBundle, peersBundle, routesBundle, - redirectsBundle + redirectsBundle, + filesBundle ) diff --git a/src/bundles/ipfs.js b/src/bundles/ipfs.js index d3c3c221a..49bf0f5b3 100644 --- a/src/bundles/ipfs.js +++ b/src/bundles/ipfs.js @@ -8,6 +8,15 @@ export default { if (action.type === 'IPFS_INIT_FINISHED') { return { ...state, ipfsReady: true } } + + if (action.type === 'IPFS_GATEWAY_URL_FINISHED') { + return { ...state, gatewayUrl: action.payload } + } + + if (!state.gatewayUrl) { + return { ...state, gatewayUrl: 'https://ipfs.io' } + } + return state }, @@ -17,7 +26,9 @@ export default { selectIpfsReady: state => state.ipfs.ipfsReady, - doInitIpfs: () => async ({ dispatch }) => { + selectGatewayUrl: state => state.ipfs.gatewayUrl, + + doInitIpfs: () => async ({ dispatch, store }) => { dispatch({ type: 'IPFS_INIT_STARTED' }) try { @@ -26,6 +37,23 @@ export default { return dispatch({ type: 'IPFS_INIT_FAILED', payload: err }) } + store.doGetGatewayUrl() dispatch({ type: 'IPFS_INIT_FINISHED' }) + }, + + doGetGatewayUrl: () => async ({ dispatch, getIpfs }) => { + dispatch({ type: 'IPFS_GATWAY_URL_STARTED' }) + + getIpfs().config.get('Addresses.Gateway', (err, res) => { + if (err) { + dispatch({ type: 'IPFS_GATWAY_URL_ERRORED', payload: err }) + return + } + + const split = res.split('/') + const gateway = '//' + split[2] + ':' + split[4] + + dispatch({ type: 'IPFS_GATWAY_URL_FINISHED', payload: gateway }) + }) } } diff --git a/src/bundles/routes.js b/src/bundles/routes.js index 20d1a0933..12dddb080 100644 --- a/src/bundles/routes.js +++ b/src/bundles/routes.js @@ -8,6 +8,7 @@ import SettingsPage from '../settings/SettingsPage' export default createRouteBundle({ '/files': FilesPage, '/explore*': IpldPage, + '/files*': FilesPage, '/peers': PeersPage, '/settings': SettingsPage, '/': StatusPage, diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 83a779c6d..db24c732d 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -1,2 +1,106 @@ import React from 'react' -export default () =>
+ {this.state.content} ++ ) + } + } +} + +export default FilesPreview diff --git a/src/files/files-list/FilesList.js b/src/files/files-list/FilesList.js index 469c8a3b2..c621462ac 100644 --- a/src/files/files-list/FilesList.js +++ b/src/files/files-list/FilesList.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import Checkbox from '../../components/checkbox/Checkbox' import SelectedActions from '../selected-actions/SelectedActions' import File from '../file/File' +import { join } from '../../lib/path' import './FilesList.css' const ORDER_BY_NAME = 'name' @@ -18,12 +19,6 @@ function compare (a, b, asc) { } } -function join (a, b) { - if (a.endsWith('/')) a = a.slice(0, -1) - if (b.startsWith('/')) b = b.slice(1) - return `${a}/${b}` -} - class FileList extends React.Component { static propTypes = { className: PropTypes.string, @@ -35,11 +30,13 @@ class FileList extends React.Component { onNavigate: PropTypes.func.isRequired, onCancelUpload: PropTypes.func.isRequired, files: PropTypes.array.isRequired, - root: PropTypes.string.isRequired + root: PropTypes.string.isRequired, + maxWidth: PropTypes.string } static defaultProps = { - className: '' + className: '', + maxWidth: '100%' } state = { @@ -70,9 +67,20 @@ class FileList extends React.Component { this.setState({selected: selected}) } - genActionFromSelected = (fn) => { + genActionFromSelected = (fn, opts = {}) => { return () => { - this.props[fn](this.selectedFiles.map(f => join(this.props.root, f.name))) + if (opts.unselect) { + this.setState({ selected: [] }) + } + + let data + if (opts.hash) { + data = this.selectedFiles.map(f => f.hash) + } else { + data = this.selectedFiles.map(f => join(this.props.root, f.name)) + } + + this.props[fn](data) } } @@ -99,12 +107,13 @@ class FileList extends React.Component { return (
Share
Inspect IPLD
-Rename
-Download
@@ -51,9 +49,17 @@ const SelectedActions = ({count, size, unselect, remove, share, download, renameDelete
Inspect IPLD
+Rename
+