From 6b5c046ccf62cda41b566fcbeaa489862db6a7bf Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 18:04:19 +0100 Subject: [PATCH 01/28] starting files page ::D --- src/bundles/files.js | 66 ++++++++++++++++++++++++++++++++++++++++++ src/bundles/index.js | 4 ++- src/bundles/routes.js | 2 ++ src/files/FilesPage.js | 65 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/bundles/files.js diff --git a/src/bundles/files.js b/src/bundles/files.js new file mode 100644 index 000000000..6684d3d20 --- /dev/null +++ b/src/bundles/files.js @@ -0,0 +1,66 @@ +import { createAsyncResourceBundle, createSelector } from 'redux-bundler' + +const bundle = createAsyncResourceBundle({ + name: 'files', + actionBaseType: 'FILES', + getPromise: (args) => { + const {store, getIpfs} = args + const path = store.selectRouteParams().path + + if (!path) { + store.doUpdateHash('/files/') + return Promise.resolve() + } + + return getIpfs().files.stat(path) + .then(stat => { + if (stat.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 { + return getIpfs().files.read(path).then(buf => { + stat.content = buf + + return { + path: path, + type: 'file', + file: stat + } + }) + } + }) + }, + 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.doFileDelete = ({getIpfs}) => {} + +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/routes.js b/src/bundles/routes.js index 20d1a0933..5bacd5e4c 100644 --- a/src/bundles/routes.js +++ b/src/bundles/routes.js @@ -8,6 +8,8 @@ import SettingsPage from '../settings/SettingsPage' export default createRouteBundle({ '/files': FilesPage, '/explore*': IpldPage, + '/files*': FilesPage, + '/ipld*': IpldPage, '/peers': PeersPage, '/settings': SettingsPage, '/': StatusPage, diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 83a779c6d..dc4015065 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -1,2 +1,65 @@ import React from 'react' -export default () =>

Files

+import PropTypes from 'prop-types' +import { connect } from 'redux-bundler-react' +import Button from '../components/button/Button' +import Breadcrumbs from './breadcrumbs/Breadcrumbs' +import FilesList from './files-list/FilesList' + +const action = (name) => { + return (...args) => { + console.log(name, args) + } +} + +class FilesPage extends React.Component { + static propTypes = { + files: PropTypes.object.isRequired + } + + onLinkClick = (link) => { + const {doUpdateHash} = this.props + doUpdateHash(`/files` + link) + } + + render () { + const {files} = this.props + + if (!files) { + return
+ } + + let body + if (files.type === 'directory') { + body = + } else { + body =

File Preview

+ } + + return ( +
+
+ + +
+ {body} +

Files

+
+ ) + } +} + +export default connect( + 'doUpdateHash', + 'selectFiles', + FilesPage +) From 81a7171625e37a9865c63e0b9270320b28ea1b5c Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 18:27:01 +0100 Subject: [PATCH 02/28] feat: delete and inspect --- src/bundles/files.js | 14 +++++++++++++- src/files/FilesPage.js | 14 ++++++++++---- src/files/files-list/FilesList.js | 19 +++++++++++++++---- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/bundles/files.js b/src/bundles/files.js index 6684d3d20..2ef9e6a72 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -61,6 +61,18 @@ bundle.reactFilesFetch = createSelector( } ) -bundle.doFileDelete = ({getIpfs}) => {} +bundle.doFilesDelete = (files) => ({dispatch, getIpfs, store, ...args}) => { + 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 }) + }) +} export default bundle diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index dc4015065..b0ad2593c 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -13,12 +13,17 @@ const action = (name) => { class FilesPage extends React.Component { static propTypes = { - files: PropTypes.object.isRequired + files: PropTypes.object } onLinkClick = (link) => { const {doUpdateHash} = this.props - doUpdateHash(`/files` + link) + doUpdateHash(`/files${link}`) + } + + onInspect = (hash) => { + const {doUpdateHash} = this.props + doUpdateHash(`/ipld/ipfs/${hash}`) } render () { @@ -34,10 +39,10 @@ class FilesPage extends React.Component { root={files.path} files={files.files} onShare={action('Share')} - onInspect={action('Inspect')} + onInspect={this.onInspect} onRename={action('Rename')} onDownload={action('Download')} - onDelete={action('Delete')} + onDelete={this.props.doFilesDelete} onNavigate={this.onLinkClick} onCancelUpload={action('Cancel Upload')} /> @@ -60,6 +65,7 @@ class FilesPage extends React.Component { export default connect( 'doUpdateHash', + 'doFilesDelete', 'selectFiles', FilesPage ) diff --git a/src/files/files-list/FilesList.js b/src/files/files-list/FilesList.js index 469c8a3b2..076df6169 100644 --- a/src/files/files-list/FilesList.js +++ b/src/files/files-list/FilesList.js @@ -70,9 +70,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) } } @@ -100,11 +111,11 @@ class FileList extends React.Component { From b71169e7cf2cd3f08f2cf84e20ce2d4f729edf1d Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 18:30:26 +0100 Subject: [PATCH 03/28] hide title --- src/files/FilesPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index b0ad2593c..38e547bab 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -57,7 +57,7 @@ class FilesPage extends React.Component {
{body} -

Files

+

Files

) } From 338ef5110ec833bbbb5224cf86f9648a7d02a7e4 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 18:32:06 +0100 Subject: [PATCH 04/28] feat: add doFilesRename --- src/bundles/files.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bundles/files.js b/src/bundles/files.js index 2ef9e6a72..946e9cbd3 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -61,7 +61,7 @@ bundle.reactFilesFetch = createSelector( } ) -bundle.doFilesDelete = (files) => ({dispatch, getIpfs, store, ...args}) => { +bundle.doFilesDelete = (files) => ({dispatch, getIpfs, store}) => { dispatch({ type: 'FILES_DELETE_STARTED' }) const promises = files.map(file => getIpfs().files.rm(file, { recursive: true })) @@ -75,4 +75,17 @@ bundle.doFilesDelete = (files) => ({dispatch, getIpfs, store, ...args}) => { }) } +bundle.doFilesRename = (from, to) => ({dispatch, getIpfs, store}) => { + dispatch({ type: 'FILES_RENAME_STARTED' }) + + return getIpfs().files.mv([from, to]) + .then(() => { + store.doFetchFiles() + dispatch({ type: 'FILES_RENAME_FINISHED' }) + }) + .catch((error) => { + dispatch({ type: 'FILES_RENAME_ERRORED', payload: error }) + }) +} + export default bundle From 9b81b000949164fb97b5155fbbeb864581e90048 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 19:57:46 +0100 Subject: [PATCH 05/28] add previews --- package-lock.json | 5 ++ package.json | 1 + src/App.js | 8 +- src/bundles/files.js | 23 +++--- src/bundles/ipfs.js | 27 ++++++ src/files/FilesPage.js | 4 +- src/files/file-icon/FileIcon.js | 35 ++++---- src/files/file-preview/FilePreview.js | 82 +++++++++++++++++++ .../extensions/audio.json | 1 - .../extensions/calc.json | 0 .../extensions/image.json | 0 .../extensions/text.json | 0 .../extensions/video.json | 0 src/files/type-from-ext/index.js | 26 ++++++ 14 files changed, 177 insertions(+), 35 deletions(-) create mode 100644 src/files/file-preview/FilePreview.js rename src/files/{file-icon => type-from-ext}/extensions/audio.json (96%) rename src/files/{file-icon => type-from-ext}/extensions/calc.json (100%) rename src/files/{file-icon => type-from-ext}/extensions/image.json (100%) rename src/files/{file-icon => type-from-ext}/extensions/text.json (100%) rename src/files/{file-icon => type-from-ext}/extensions/video.json (100%) create mode 100644 src/files/type-from-ext/index.js diff --git a/package-lock.json b/package-lock.json index 1b5a135c0..328844b87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8867,6 +8867,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", 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..c60f3ea6c 100644 --- a/src/App.js +++ b/src/App.js @@ -45,4 +45,10 @@ export class App extends Component { } } -export default connect('selectRoute', 'doUpdateUrl', 'doInitIpfs', App) +export default connect( + 'selectRoute', + 'doUpdateUrl', + 'doInitIpfs', + 'doGetGatewayUrl', + App +) diff --git a/src/bundles/files.js b/src/bundles/files.js index 946e9cbd3..7f7cf5cff 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -5,16 +5,18 @@ const bundle = createAsyncResourceBundle({ actionBaseType: 'FILES', getPromise: (args) => { const {store, getIpfs} = args - const path = store.selectRouteParams().path + let path = store.selectRouteParams().path if (!path) { store.doUpdateHash('/files/') return Promise.resolve() } + path = decodeURIComponent(path) + return getIpfs().files.stat(path) - .then(stat => { - if (stat.type === 'directory') { + .then(stats => { + if (stats.type === 'directory') { return getIpfs().files.ls(path, {l: true}).then((res) => { // FIX: open PR on js-ipfs-api if (res) { @@ -31,15 +33,14 @@ const bundle = createAsyncResourceBundle({ } }) } else { - return getIpfs().files.read(path).then(buf => { - stat.content = buf + stats.name = path - return { - path: path, - type: 'file', - file: stat - } - }) + return { + path: path, + type: 'file', + stats: stats, + read: () => getIpfs().files.read(path) + } } }) }, diff --git a/src/bundles/ipfs.js b/src/bundles/ipfs.js index d3c3c221a..2d34a994c 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,6 +26,8 @@ export default { selectIpfsReady: state => state.ipfs.ipfsReady, + selectGatewayUrl: state => state.ipfs.gatewayUrl, + doInitIpfs: () => async ({ dispatch }) => { dispatch({ type: 'IPFS_INIT_STARTED' }) @@ -27,5 +38,21 @@ export default { } dispatch({ type: 'IPFS_INIT_FINISHED' }) + }, + + doGetGatewayUrl: () => async ({ dispatch }) => { + 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/files/FilesPage.js b/src/files/FilesPage.js index 38e547bab..8f333f805 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -4,6 +4,7 @@ import { connect } from 'redux-bundler-react' import Button from '../components/button/Button' import Breadcrumbs from './breadcrumbs/Breadcrumbs' import FilesList from './files-list/FilesList' +import FilePreview from './file-preview/FilePreview' const action = (name) => { return (...args) => { @@ -47,7 +48,7 @@ class FilesPage extends React.Component { onCancelUpload={action('Cancel Upload')} /> } else { - body =

File Preview

+ body = } return ( @@ -67,5 +68,6 @@ export default connect( 'doUpdateHash', 'doFilesDelete', 'selectFiles', + 'selectGatewayUrl', FilesPage ) diff --git a/src/files/file-icon/FileIcon.js b/src/files/file-icon/FileIcon.js index cb270e314..7108d5561 100644 --- a/src/files/file-icon/FileIcon.js +++ b/src/files/file-icon/FileIcon.js @@ -1,11 +1,5 @@ import React from 'react' -import fileExtension from 'file-extension' - -import audioExtensions from './extensions/audio.json' -import calcExtensions from './extensions/calc.json' -import imageExtensions from './extensions/image.json' -import videoExtensions from './extensions/video.json' -import textExtensions from './extensions/text.json' +import typeFromExt from '../type-from-ext' import Folder from '../../icons/GlyphFolder' import Doc from '../../icons/StrokeDocument' @@ -16,23 +10,22 @@ import DocPicture from '../../icons/GlyphDocPicture' import DocText from '../../icons/GlyphDocText' export default function FileIcon ({name, type}) { - const ext = fileExtension(name) - if (type === 'directory') { return } - if (audioExtensions.includes(ext)) { - return - } else if (calcExtensions.includes(ext)) { - return - } else if (imageExtensions.includes(ext)) { - return - } else if (videoExtensions.includes(ext)) { - return - } else if (textExtensions.includes(ext)) { - return + switch (typeFromExt(name)) { + case 'audio': + return + case 'calc': + return + case 'video': + return + case 'text': + return + case 'image': + return + default: + return } - - return } diff --git a/src/files/file-preview/FilePreview.js b/src/files/file-preview/FilePreview.js new file mode 100644 index 000000000..cb22f70ed --- /dev/null +++ b/src/files/file-preview/FilePreview.js @@ -0,0 +1,82 @@ +import React from 'react' +import PropTypes from 'prop-types' +import isBinary from 'is-binary' +import fileExtension from 'file-extension' +import typeFromExt from '../type-from-ext' + +class FilesPreview extends React.Component { + static propTypes = { + stats: PropTypes.object.isRequired, + gatewayUrl: PropTypes.string.isRequired, + read: PropTypes.func.isRequired, + content: PropTypes.object + } + + state = { + content: null + } + + loadContent () { + this.props.read() + .then(buf => { + this.setState({ content: buf.toString('utf-8') }) + }) + } + + render () { + const {stats, gatewayUrl} = this.props + + const type = typeFromExt(stats.name) + const src = `${gatewayUrl}/ipfs/${stats.hash}` + const ext = fileExtension(stats.name) + const className = 'w-100 bg-snow-muted pa2 br2' + switch (type) { + case 'audio': + return ( + + ) + case 'pdf': + return ( + + ) + case 'video': + console.log('Ivdeo') + return ( + + ) + case 'image': + return {stats.name} + default: + const cantPreview = ( +
+ Sorry, we can not preview this file.. +
+ ) + + if (stats.size > 1024 * 1024 * 4) { + return cantPreview + } + + if (!this.state.content) { + this.loadContent() + return
Loading
+ } + + if (isBinary(this.state.content)) { + return cantPreview + } + + return ( +
+            {this.state.content}
+          
+ ) + } + } +} + +export default FilesPreview diff --git a/src/files/file-icon/extensions/audio.json b/src/files/type-from-ext/extensions/audio.json similarity index 96% rename from src/files/file-icon/extensions/audio.json rename to src/files/type-from-ext/extensions/audio.json index 617d45e24..581929bb0 100644 --- a/src/files/file-icon/extensions/audio.json +++ b/src/files/type-from-ext/extensions/audio.json @@ -12,7 +12,6 @@ "aac", "mp2", "mp3", - "mp4", "amr", "s3m", "3gp", diff --git a/src/files/file-icon/extensions/calc.json b/src/files/type-from-ext/extensions/calc.json similarity index 100% rename from src/files/file-icon/extensions/calc.json rename to src/files/type-from-ext/extensions/calc.json diff --git a/src/files/file-icon/extensions/image.json b/src/files/type-from-ext/extensions/image.json similarity index 100% rename from src/files/file-icon/extensions/image.json rename to src/files/type-from-ext/extensions/image.json diff --git a/src/files/file-icon/extensions/text.json b/src/files/type-from-ext/extensions/text.json similarity index 100% rename from src/files/file-icon/extensions/text.json rename to src/files/type-from-ext/extensions/text.json diff --git a/src/files/file-icon/extensions/video.json b/src/files/type-from-ext/extensions/video.json similarity index 100% rename from src/files/file-icon/extensions/video.json rename to src/files/type-from-ext/extensions/video.json diff --git a/src/files/type-from-ext/index.js b/src/files/type-from-ext/index.js new file mode 100644 index 000000000..53d3e1a89 --- /dev/null +++ b/src/files/type-from-ext/index.js @@ -0,0 +1,26 @@ +import fileExtension from 'file-extension' +import audioExtensions from './extensions/audio.json' +import calcExtensions from './extensions/calc.json' +import imageExtensions from './extensions/image.json' +import videoExtensions from './extensions/video.json' +import textExtensions from './extensions/text.json' + +export default function FileIcon (filename) { + const ext = fileExtension(filename) + + if (ext === 'pdf') { + return 'pdf' + } else if (audioExtensions.includes(ext)) { + return 'audio' + } else if (calcExtensions.includes(ext)) { + return 'calc' + } else if (imageExtensions.includes(ext)) { + return 'image' + } else if (videoExtensions.includes(ext)) { + return 'video' + } else if (textExtensions.includes(ext)) { + return 'text' + } + + return 'blob' +} From 5acc5d651af29b220bc214e1988be861aff066d1 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 20:07:29 +0100 Subject: [PATCH 06/28] fix links, package json and remove route --- package-lock.json | 222 ++++++++++++++++------------------------- src/bundles/routes.js | 1 - src/files/FilesPage.js | 2 +- 3 files changed, 88 insertions(+), 137 deletions(-) diff --git a/package-lock.json b/package-lock.json index 328844b87..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": { @@ -9123,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", @@ -10377,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", @@ -10920,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", @@ -12029,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": { @@ -13022,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", @@ -13882,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", @@ -14085,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", @@ -14097,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", @@ -14260,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": { @@ -14699,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", @@ -14925,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", @@ -15596,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", @@ -15891,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" @@ -16033,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/src/bundles/routes.js b/src/bundles/routes.js index 5bacd5e4c..12dddb080 100644 --- a/src/bundles/routes.js +++ b/src/bundles/routes.js @@ -9,7 +9,6 @@ export default createRouteBundle({ '/files': FilesPage, '/explore*': IpldPage, '/files*': FilesPage, - '/ipld*': IpldPage, '/peers': PeersPage, '/settings': SettingsPage, '/': StatusPage, diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 8f333f805..a65a0ec42 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -24,7 +24,7 @@ class FilesPage extends React.Component { onInspect = (hash) => { const {doUpdateHash} = this.props - doUpdateHash(`/ipld/ipfs/${hash}`) + doUpdateHash(`/explore/ipfs/${hash}`) } render () { From c7b88544c11c5df90a42d0a2f505a466b10f84eb Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 23:42:13 +0100 Subject: [PATCH 07/28] fix breadcrumbs --- src/files/breadcrumbs/Breadcrumbs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/files/breadcrumbs/Breadcrumbs.js b/src/files/breadcrumbs/Breadcrumbs.js index b82950238..3ecd8bc18 100644 --- a/src/files/breadcrumbs/Breadcrumbs.js +++ b/src/files/breadcrumbs/Breadcrumbs.js @@ -14,8 +14,6 @@ function makeBread (root) { } }) - parts[0].name = 'Root' - for (let i = 1; i < parts.length; i++) { parts[i] = { name: parts[i].name, @@ -23,6 +21,9 @@ function makeBread (root) { } } + parts[0].name = 'Root' + parts[0].path = '/' + return parts } From 12508ac245640f63ed6f4bf643f262318088ea64 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 23:42:19 +0100 Subject: [PATCH 08/28] add message when folder is empty --- src/files/FilesPage.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index a65a0ec42..385e00f8d 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -12,6 +12,12 @@ const action = (name) => { } } +const empty = ( +
+

It seems a bit lonely here :(

+
+) + class FilesPage extends React.Component { static propTypes = { files: PropTypes.object @@ -36,17 +42,21 @@ class FilesPage extends React.Component { let body if (files.type === 'directory') { - body = + if (files.files.length === 0) { + body = empty + } else { + body = + } } else { body = } From af62ed497fd35e7e1b0fc4b823de413f69ae5f60 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Wed, 23 May 2018 23:52:53 +0100 Subject: [PATCH 09/28] add alternative message file preview --- src/files/file-preview/FilePreview.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/files/file-preview/FilePreview.js b/src/files/file-preview/FilePreview.js index cb22f70ed..532042915 100644 --- a/src/files/file-preview/FilePreview.js +++ b/src/files/file-preview/FilePreview.js @@ -39,7 +39,10 @@ class FilesPreview extends React.Component { ) case 'pdf': return ( - + + If you're seeing this, is because your browser doesn't support previwing + PDF files. + ) case 'video': console.log('Ivdeo') From 4b6fd6b4c2fcd24454e96954c6817cd4cfb3dc78 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 11:43:10 +0100 Subject: [PATCH 10/28] display titlte --- src/files/FilesPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 385e00f8d..01f34a115 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -68,7 +68,7 @@ class FilesPage extends React.Component { {body} -

Files

+

Files

) } From 72bcab7804d2420bde2f3d5bebbd78d9dce86145 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 12:51:32 +0100 Subject: [PATCH 11/28] make tests pass --- src/files/FilesPage.js | 4 +++- src/files/file-preview/FilePreview.js | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 01f34a115..76503df34 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -37,7 +37,9 @@ class FilesPage extends React.Component { const {files} = this.props if (!files) { - return
+ return
+

Files

+
} let body diff --git a/src/files/file-preview/FilePreview.js b/src/files/file-preview/FilePreview.js index 532042915..fd3f9fef8 100644 --- a/src/files/file-preview/FilePreview.js +++ b/src/files/file-preview/FilePreview.js @@ -40,8 +40,7 @@ class FilesPreview extends React.Component { case 'pdf': return ( - If you're seeing this, is because your browser doesn't support previwing - PDF files. + ) case 'video': From 88dbb954e59f12f853c2077c3c2ca5edf1eca7db Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 12:56:44 +0100 Subject: [PATCH 12/28] readd unsupported message --- src/files/file-preview/FilePreview.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/files/file-preview/FilePreview.js b/src/files/file-preview/FilePreview.js index fd3f9fef8..532042915 100644 --- a/src/files/file-preview/FilePreview.js +++ b/src/files/file-preview/FilePreview.js @@ -40,7 +40,8 @@ class FilesPreview extends React.Component { case 'pdf': return ( - + If you're seeing this, is because your browser doesn't support previwing + PDF files. ) case 'video': From 9d74d90b7632d85ab3c7b2609c71b0a70cfb2c92 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 12:59:48 +0100 Subject: [PATCH 13/28] feat: rename is working with ugly prompt --- src/files/FilesPage.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index 76503df34..b7c506d19 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -33,6 +33,13 @@ class FilesPage extends React.Component { doUpdateHash(`/explore/ipfs/${hash}`) } + onRename = ([path]) => { + let currentName = path.split('/').pop() + let newName = window.prompt("What's the new name?") + + this.props.doFilesRename(path, path.replace(currentName, newName)) + } + render () { const {files} = this.props @@ -52,7 +59,7 @@ class FilesPage extends React.Component { files={files.files} onShare={action('Share')} onInspect={this.onInspect} - onRename={action('Rename')} + onRename={this.onRename} onDownload={action('Download')} onDelete={this.props.doFilesDelete} onNavigate={this.onLinkClick} @@ -79,6 +86,7 @@ class FilesPage extends React.Component { export default connect( 'doUpdateHash', 'doFilesDelete', + 'doFilesRename', 'selectFiles', 'selectGatewayUrl', FilesPage From 2e1ce94c1056efdde99f37300597fcd640336b8d Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 14:32:42 +0100 Subject: [PATCH 14/28] better renaming --- src/files/FilesPage.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index b7c506d19..c3c14976c 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -23,7 +23,7 @@ class FilesPage extends React.Component { files: PropTypes.object } - onLinkClick = (link) => { + onLinkClick = (link) => { const {doUpdateHash} = this.props doUpdateHash(`/files${link}`) } @@ -34,10 +34,12 @@ class FilesPage extends React.Component { } onRename = ([path]) => { - let currentName = path.split('/').pop() - let newName = window.prompt("What's the new name?") + const oldName = path.split('/').pop() + const newName = window.prompt('Insert the new name:') - this.props.doFilesRename(path, path.replace(currentName, newName)) + if (newName) { + this.props.doFilesRename(path, path.replace(oldName, newName)) + } } render () { From 87331b30cf3616b2ee6cdb8db7be9b8c15fc6a61 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 14:32:51 +0100 Subject: [PATCH 15/28] add mkdir bundle --- src/bundles/files.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/bundles/files.js b/src/bundles/files.js index 7f7cf5cff..1ce788895 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -89,4 +89,17 @@ bundle.doFilesRename = (from, to) => ({dispatch, getIpfs, store}) => { }) } +bundle.doFilesMakeDir = (path) => ({dispatch, getIpfs, store}) => { + dispatch({ type: 'FILES_MKDIR_STARTED' }) + + return getIpfs().files.mkdir(path, { parents: true }) + .then(() => { + store.doFetchFiles() + dispatch({ type: 'FILES_MKDIR_FINISHED' }) + }) + .catch((error) => { + dispatch({ type: 'FILES_MKDIR_ERRORED', payload: error }) + }) +} + export default bundle From 136deeefc315c7755b22e408cbdc38a0b0e5349e Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 14:38:25 +0100 Subject: [PATCH 16/28] add bundle files write --- src/bundles/files.js | 15 +++++++++++++++ src/files/files-list/FilesList.js | 7 +------ src/lib/path.js | 6 ++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/bundles/files.js b/src/bundles/files.js index 1ce788895..81fa22401 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -1,4 +1,5 @@ import { createAsyncResourceBundle, createSelector } from 'redux-bundler' +import { join } from '../lib/path' const bundle = createAsyncResourceBundle({ name: 'files', @@ -102,4 +103,18 @@ bundle.doFilesMakeDir = (path) => ({dispatch, getIpfs, store}) => { }) } +bundle.doFilesWrite = (root, files) => ({dispatch, getIpfs, store}) => { + dispatch({ type: 'FILES_WRITE_STARTED' }) + + 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/files/files-list/FilesList.js b/src/files/files-list/FilesList.js index 076df6169..2413d0c5c 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, diff --git a/src/lib/path.js b/src/lib/path.js index 8c2d890ef..de2fc4355 100644 --- a/src/lib/path.js +++ b/src/lib/path.js @@ -17,3 +17,9 @@ export function quickSplitPath (str) { address: res[0] // /ipfs/QmHash/foo/bar } } + +export function join (a, b) { + if (a.endsWith('/')) a = a.slice(0, -1) + if (b.startsWith('/')) b = b.slice(1) + return `${a}/${b}` +} From 3837533f4c04eb2c24ea2d45fcd5b45acf6995bb Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 14:53:09 +0100 Subject: [PATCH 17/28] Upload files working --- src/files/FilesPage.js | 9 ++++- src/files/file-input/FileInput.js | 62 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/files/file-input/FileInput.js diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index c3c14976c..f6e51fb6d 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -1,10 +1,10 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'redux-bundler-react' -import Button from '../components/button/Button' import Breadcrumbs from './breadcrumbs/Breadcrumbs' import FilesList from './files-list/FilesList' import FilePreview from './file-preview/FilePreview' +import FileInput from './file-input/FileInput' const action = (name) => { return (...args) => { @@ -42,6 +42,10 @@ class FilesPage extends React.Component { } } + onFilesUpload = (files) => { + this.props.doFilesWrite(this.props.files.path, files) + } + render () { const {files} = this.props @@ -76,7 +80,7 @@ class FilesPage extends React.Component {
- +
{body}

Files

@@ -89,6 +93,7 @@ export default connect( 'doUpdateHash', 'doFilesDelete', 'doFilesRename', + 'doFilesWrite', 'selectFiles', 'selectGatewayUrl', FilesPage diff --git a/src/files/file-input/FileInput.js b/src/files/file-input/FileInput.js new file mode 100644 index 000000000..6bc1fbc30 --- /dev/null +++ b/src/files/file-input/FileInput.js @@ -0,0 +1,62 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Button from '../../components/button/Button' + +export 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) + }) +} + +export default class FileInput extends React.Component { + static propTypes = { + upload: PropTypes.func.isRequired + } + + onChange = () => { + const raw = this.input.files + const { upload } = this.props + let promises = [] + + for (const file of raw) { + promises.push(readAsBuffer(file)) + console.log(file) + } + + Promise.all(promises) + .then(files => { + upload(files) + }) + + this.input.value = null + } + + onClick = () => { + this.input.click() + } + + render () { + return ( +
+ + { this.input = input }} + onChange={this.onChange} /> +
+ ) + } +} From 7648cd240d5a800e55f9df799367bfbdcf0a7444 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 24 May 2018 15:00:14 +0100 Subject: [PATCH 18/28] add max width to bar --- src/files/FilesPage.js | 3 ++- src/files/files-list/FilesList.js | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index f6e51fb6d..671c4c1ae 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -23,7 +23,7 @@ class FilesPage extends React.Component { files: PropTypes.object } - onLinkClick = (link) => { + onLinkClick = (link) => { const {doUpdateHash} = this.props doUpdateHash(`/files${link}`) } @@ -61,6 +61,7 @@ class FilesPage extends React.Component { body = empty } else { body = Date: Thu, 24 May 2018 15:33:32 +0100 Subject: [PATCH 19/28] fix small issues --- src/bundles/files.js | 2 ++ src/files/files-list/FilesList.js | 2 +- src/navigation/NavBar.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bundles/files.js b/src/bundles/files.js index 81fa22401..0fe0015ac 100644 --- a/src/bundles/files.js +++ b/src/bundles/files.js @@ -13,6 +13,8 @@ const bundle = createAsyncResourceBundle({ return Promise.resolve() } + // FIX: dirs with actually encoded names + // will get decoded... it shouldn't happen path = decodeURIComponent(path) return getIpfs().files.stat(path) diff --git a/src/files/files-list/FilesList.js b/src/files/files-list/FilesList.js index 7df28829e..c621462ac 100644 --- a/src/files/files-list/FilesList.js +++ b/src/files/files-list/FilesList.js @@ -141,7 +141,7 @@ class FileList extends React.Component { onNavigate={this.genActionFromFile('onNavigate', file)} onCancel={this.genActionFromFile('onCancelUpload', file)} selected={this.state.selected.indexOf(file.hash) !== -1} - key={file.hash} + key={window.btoa(file.name)} {...file} /> )) diff --git a/src/navigation/NavBar.js b/src/navigation/NavBar.js index 346ab2495..f9889cfb1 100644 --- a/src/navigation/NavBar.js +++ b/src/navigation/NavBar.js @@ -43,7 +43,7 @@ export default () => (
) case 'video': - console.log('Ivdeo') return (