diff --git a/examples/exchange-files-in-browser/.gitignore b/examples/exchange-files-in-browser/.gitignore index 74e9f3ccf0..e4615cfea1 100644 --- a/examples/exchange-files-in-browser/.gitignore +++ b/examples/exchange-files-in-browser/.gitignore @@ -1 +1,2 @@ public/js/ipfs.js +*.lock \ No newline at end of file diff --git a/examples/exchange-files-in-browser/public/css/app.css b/examples/exchange-files-in-browser/public/css/app.css index 59cfeb2d1a..32667fc685 100644 --- a/examples/exchange-files-in-browser/public/css/app.css +++ b/examples/exchange-files-in-browser/public/css/app.css @@ -1,38 +1,19 @@ +* { + box-sizing: border-box; +} + body { - height: 100vh; + min-height: 100vh; font-family: sans-serif; color: white; background: linear-gradient(to bottom,#041727 0%,#062b3f 100%); pointer-events: auto; -} - -.dragover-popup { - position: absolute; - top: 10px; right: 10px; bottom: 10px; left: 10px; - background-color: rgba(0, 0, 0, 0.5); - text-align: center; - padding-top: 30%; - display: none; - pointer-events: none; -} - -.wrapper { - width: 900px; - margin: 0 auto; - /* filter: blur(5px); */ -} - -.header { - text-align: center; - /* filter: blur(5px); */ -} - -#filesStatus { - padding: 10px; + padding: 0; + margin: 0; } h1, h2, h3 { - margin: 0px; + margin: 0; } h1 { @@ -50,48 +31,56 @@ h3 { font-weight: 700; } - -.header h1 { - margin-top: 20px; - margin-bottom: 20px; +main, +header { + filter: none; } -.hidden { +.dragover-popup { + position: fixed; + top: 0.5em; + left: 0.5em; + width: calc(100% - 1em); + height: calc(100% - 1em); + background-color: rgba(0, 0, 0, 0.5); display: none; + pointer-events: none; } -.visible { - display: inherit; - font-size: 0.8em; +.dragover-popup h1 { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) } -.error { - font-style: italic; - color: red; +body.dragging main, +body.dragging header { + filter: blur(5px); } -.ipfs { - padding-bottom: 50px; - border-radius: 1px; - box-sizing: border-box; +body.dragging .dragover-popup { + display: block; } -#details { - padding: 10px; - width: 100%; - box-sizing: border-box; +header { + text-align: center; + display: flex; + justify-content: center; + align-items: center; + padding: 3em 0; } ul { - margin: 0px; padding: 0px; + margin: 0; + padding: 0; list-style: none; - font-size: 11px; } ul li { - margin-top: 10px; - margin-bottom: 10px; - font-size: 9px; + margin: 1em 0; + font-size: 0.7em; + font-family: monospace; word-wrap: break-word; } @@ -99,43 +88,15 @@ button { background-color: rgba(0,0,0,0.2); color: #6acad1; border: 2px solid #6acad1; - font-size: 15px; - padding: 10px 25px 10px 25px; - border-radius: 2px; - margin: 5px; -} - -.multihash-wrapper input { - width: 80%; - float: left; - height: 40px; - margin-left: 1%; - font-size: 16px; - box-sizing: border-box; + font-size: 1em; + padding: 0.625em 1.5em; + border-radius: 0.125em; + margin: .5em 0; } -.multihash-wrapper button { - width: 17%; - float: left; - height: 40px; - margin: 0px; - margin-left: 1%; -} - -.file-list { - display: block; - margin: 10px; -} - -.file-list a { - font-size: 16px; - color: white; - display: block; -} - -button.connect-peer { - margin: 0px; - margin-top: 2px; +button.full { + margin-right: 0; + margin-left: 0; width: 100%; } @@ -149,101 +110,138 @@ button:hover { font-family: monospace } +.disabled *, +input:disabled, button:disabled { opacity: 0.2; } -input:disabled { - opacity: 0.2; -} -.disabled { - opacity: 0.2; -} input { width: 100%; - border: 2px solid #444; + border: 2px solid rgba(0,0,0,0.2); color: black; - padding: 7px; + padding: 0.7em; border-radius: 2px; - font-size: 9px; - box-sizing: border-box; } -textarea, input, button { +input:hover, input:focus, input:active { + border-color: #6acad1; +} + +input, button { outline: none; } -button:focus, input:focus { - outline: 3px solid #6acad1; +main { + width: 90%; + margin: 0 auto; } -.picture { - margin-top: 1em; - width: 100%; - background-color: rgba(196, 196, 196, 0.1); - /*padding: 0.25em;*/ - /*font-size: 1.2em;*/ +.buttons, +.columns { + display: flex; + flex-direction: row; + justify-content: space-between; } -.settings { - padding: 15px; +.buttons > button, +.columns > div { + width: calc(50% - 0.5em); } -.left { - box-sizing: border-box; - /* background-color: red; */ +.buttons > button { + margin: 0 0 1em; } -.right { - /* background-color: green; */ +.box { + background-color: rgba(255, 255, 255, 0.05); + padding: 1em; + margin-bottom: 1em; } -.setting-item { - margin-top: 20px; +.box > h2 { + display: block; + border-bottom: 2px solid rgba(255, 255, 255, 0.1); + border-right: 0; + border-left: 0; + text-align: center; + padding-bottom: 0.5em; + margin-bottom: 1em; } -.left, .right { - width: 48%; - float: left; - background-color: rgba(255, 255, 255, 0.05); - box-sizing: border-box; - margin: 1%; - padding: 10px; +#peers i { + display: none; + margin-top: 5px; + margin-bottom: 5px; + font-size: 14px; +} + +#peers.waiting i { + display: block; +} + +#errors { + grid-area: errors; + color: red; + font-style: italic; + font-size: 1.125em; + display: block; + margin: 0 0 1em; } +#errors.hidden { + display: none; +} +#note { + position: absolute; + top: 1em; + right: 1em; + font-size: 0.625em; +} -#files { - padding-top: 10px; - background-color: rgba(255, 255, 255, 0.05); - margin: 1%; +#file-status { + font-style: italic; + color: cyan; + font-size: 0.8em; + margin: 1em 0; } -.left.centered { - float: none; - margin: 0px auto; - text-align: center; +table { + width: 100%; + margin: 1em 0; + word-break: break-all; + border-collapse: collapse; } -.clear { - clear: both; +table thead { + background-color: rgba(255, 255, 255, 0.1); + font-weight: normal } -.note { - position: absolute; - top: 10px; - right: 10px; - font-size: 10px; - font-size: 10px; +table th, table td { + padding: 0.5em 0; } -#peers i { - display: block; - margin-top: 5px; - margin-bottom: 5px; - font-size: 14px; +table td:last-child, +table th:last-child { + width: 20%; + text-align: center; } -.error { - font-size: 18px; +table td:first-child { + width: 45%; } + +table td:nth-child(2) { + width: 35%; + font-family: monospace; +} + +table tr:hover { + background-color: rgba(0, 0, 0, 0.2) +} + +table a { + color: inherit; +} \ No newline at end of file diff --git a/examples/exchange-files-in-browser/public/index.html b/examples/exchange-files-in-browser/public/index.html index 6602f7c52e..a526f9a26d 100644 --- a/examples/exchange-files-in-browser/public/index.html +++ b/examples/exchange-files-in-browser/public/index.html @@ -11,59 +11,65 @@

Drop file to upload

-
- - - -

Transfer Files

-
- P.S. drop files anywhere to upload them! -
-
+
+

IPFS | InterPlanetary File Exchange

+ P.S. drop files anywhere to upload them! +
-
-
-
-
- - -
-
+
+ + +
+
+

Your daemon

-

ID

-
N/A
-

Addresses

-
    -
  • Not yet online
  • -
+
+ + +
+
+

ID

+
N/A
+

Addresses

+
    +
  • Not yet online
  • +
+
-
-
-
+ +

Peers

-
-
- - + + + Waiting for peers... +
    -
    -
    -
    - - -
    -
    -
    -
    + +
    +

    Files

    + + + + +

    + + + + + + + + + + +
    NameCIDSize
    - -
    -
    +
    - - - + + + diff --git a/examples/exchange-files-in-browser/public/js/app.js b/examples/exchange-files-in-browser/public/js/app.js index 7b54655be5..778ca44c1c 100644 --- a/examples/exchange-files-in-browser/public/js/app.js +++ b/examples/exchange-files-in-browser/public/js/app.js @@ -4,25 +4,24 @@ const $startButton = document.querySelector('#start') const $stopButton = document.querySelector('#stop') const $peers = document.querySelector('#peers') +const $peersList = $peers.querySelector('ul') const $errors = document.querySelector('#errors') -const $filesStatus = document.querySelector('#filesStatus') +const $fileHistory = document.querySelector('#file-history tbody') +const $fileStatus = document.querySelector('#file-status') const $multihashInput = document.querySelector('#multihash') const $catButton = document.querySelector('#cat') -const $connectPeer = document.querySelector('input.connect-peer') -const $connectPeerButton = document.querySelector('button.connect-peer') -const $dragoverPopup = document.querySelector('.dragover-popup') -const $wrapper = document.querySelector('.wrapper') -const $header = document.querySelector('.header') +const $connectPeer = document.querySelector('#peer-input') +const $connectPeerButton = document.querySelector('#peer-btn') const $body = document.querySelector('body') const $idContainer = document.querySelector('.id-container') const $addressesContainer = document.querySelector('.addresses-container') -const $details = document.querySelector('#details') const $allDisabledButtons = document.querySelectorAll('button:disabled') const $allDisabledInputs = document.querySelectorAll('input:disabled') -const $filesList = document.querySelector('.file-list') +const $allDisabledElements = document.querySelectorAll('.disabled') let node let info +let Buffer /* * Start and stop the IPFS node @@ -45,12 +44,14 @@ function start () { } // IFDEV: To test with latest js-ipfs - const IPFS = require('ipfs') - node = new IPFS(options) + // const IPFS = require('ipfs') + // node = new IPFS(options) // VEDIF // EXAMPLE - // node = new self.Ipfs(options) + node = new self.Ipfs(options) + + Buffer = node.types.Buffer node.once('start', () => node.id((err, id) => { if (err) { return onError(err) } @@ -58,7 +59,7 @@ function start () { info = id updateView('ready', node) setInterval(refreshPeerList, 1000) - $peers.innerHTML = '

    peers

    waiting for peers...' + $peers.classList.add('waiting') })) } } @@ -67,23 +68,29 @@ function stop () { window.location.href = window.location.href // refresh page } -/* - * Fetch files and display them to the user - */ - -function createFileBlob (data, multihash) { +function appendFile (name, hash, size, data) { const file = new window.Blob([data], { type: 'application/octet-binary' }) - const fileUrl = window.URL.createObjectURL(file) - - const listItem = document.createElement('div') + const url = window.URL.createObjectURL(file) + const row = document.createElement('tr') + + const nameCell = document.createElement('td') + nameCell.innerHTML = name + + const hashCell = document.createElement('td') const link = document.createElement('a') - link.setAttribute('href', fileUrl) - link.setAttribute('download', multihash) - const date = (new Date()).toLocaleTimeString() + link.innerHTML = hash + link.setAttribute('href', url) + link.setAttribute('download', name) + hashCell.appendChild(link) + + const sizeCell = document.createElement('td') + sizeCell.innerText = size - link.innerText = date + ' - ' + multihash + ' - Size: ' + file.size - listItem.appendChild(link) - return listItem + row.appendChild(nameCell) + row.appendChild(hashCell) + row.appendChild(sizeCell) + + $fileHistory.insertBefore(row, $fileHistory.firstChild) } function getFile () { @@ -91,7 +98,7 @@ function getFile () { $multihashInput.value = '' - $errors.className = 'hidden' + $errors.classList.add('hidden') if (!cid) { return console.log('no multihash was inserted') } @@ -100,8 +107,7 @@ function getFile () { files.forEach((file) => { if (file.content) { - const listItem = createFileBlob(file.content, cid) - $filesList.insertBefore(listItem, $filesList.firstChild) + appendFile(file.name, cid, file.size, file.content) } }) }) @@ -112,7 +118,7 @@ function getFile () { */ function onDrop (event) { onDragExit() - $errors.className = 'hidden' + $errors.classList.add('hidden') event.preventDefault() if (!node) { @@ -137,12 +143,14 @@ function onDrop (event) { files.forEach((file) => { readFileContents(file) .then((buffer) => { - node.files.add(Buffer.from(buffer), (err, filesAdded) => { + node.files.add({ + path: file.name, + content: Buffer.from(buffer) + }, { wrap: true }, (err, filesAdded) => { if (err) { return onError(err) } - const fl = filesAdded[0] - $multihashInput.value = fl.hash - $filesStatus.innerHTML = `Added ${file.name} as ${fl.hash}` + $multihashInput.value = filesAdded[0].hash + $fileStatus.innerHTML = `${file.name} added! Try to hit 'Fetch' button!` }) }) .catch(onError) @@ -188,9 +196,12 @@ function refreshPeerList () { return '
  • ' + addr + '
  • ' }).join('') - $peers.innerHTML = peers.length > 0 - ? '

    Remote Peers

      ' + peersAsHtml + '
    ' - : '

    Remote Peers

    Waiting for peers...' + if (peers.length === 0) { + $peers.classList.add('waiting') + } else { + $peers.classList.remove('waiting') + $peersList.innerHTML = peersAsHtml + } }) } @@ -207,22 +218,18 @@ function onError (err) { msg = err } - $errors.innerHTML = '' + msg + '' - $errors.className = 'error visible' + $errors.innerHTML = msg + $errors.classList.remove('hidden') } window.onerror = onError function onDragEnter () { - $dragoverPopup.style.display = 'block' - $wrapper.style.filter = 'blur(5px)' - $header.style.filter = 'blur(5px)' + $body.classList.add('dragging') } function onDragExit () { - $dragoverPopup.style.display = 'none' - $wrapper.style.filter = '' - $header.style.filter = '' + $body.classList.remove('dragging') } /* @@ -237,8 +244,7 @@ const states = { $addressesContainer.innerHTML = addressesHtml $allDisabledButtons.forEach(b => { b.disabled = false }) $allDisabledInputs.forEach(b => { b.disabled = false }) - $peers.className = '' - $details.className = '' + $allDisabledElements.forEach(el => { el.classList.remove('disabled') }) $stopButton.disabled = false $startButton.disabled = true }, @@ -262,7 +268,6 @@ const startApplication = () => { // Setup event listeners $body.addEventListener('dragenter', onDragEnter) $body.addEventListener('drop', onDrop) - // TODO should work to hide the dragover-popup but doesn't... $body.addEventListener('dragleave', onDragExit) $startButton.addEventListener('click', start)