├── .gitignore ├── LICENSE ├── README.md ├── app.js ├── extend.plist ├── icons ├── dark.png ├── dark@2x.png ├── white.png └── white@2x.png ├── images ├── cat-1.png ├── cat-2.png ├── cat-3.png ├── cat-4.png ├── cat-5.png ├── cat-6.png └── cat-7.png ├── index.html ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Mathias Buus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dat-drop 2 | 3 | WIP - nothing to see here 4 | 5 | ``` 6 | npm install dat-drop 7 | ``` 8 | 9 | ## Usage 10 | 11 | ``` js 12 | var dat-drop = require('dat-drop') 13 | ``` 14 | 15 | ## License 16 | 17 | MIT 18 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var electron = require('electron') 2 | 3 | var win = null 4 | var tray = null 5 | 6 | electron.app.on('ready', function () { 7 | win = new electron.BrowserWindow({ 8 | width: 550, 9 | height: 500, 10 | backgroundColor: '#293648' 11 | }) 12 | 13 | win.loadURL(`file://${__dirname}/index.html`) 14 | 15 | win.on('closed', function () { 16 | win = null 17 | tray = null 18 | }) 19 | 20 | var color = electron.systemPreferences.isDarkMode() 21 | ? 'white' 22 | : 'dark' 23 | tray = new electron.Tray(`${__dirname}/icons/${color}.png`) 24 | tray.setToolTip('Drop files here') 25 | tray.on('drop-files', function (e, files) { 26 | win.webContents.send('drop', files) 27 | }) 28 | }) 29 | 30 | electron.app.on('will-finish-launching', function () { 31 | electron.app.on('open-url', function (ev, url) { 32 | // send the url to the renderer process via rpc 33 | ev.preventDefault() 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /extend.plist: -------------------------------------------------------------------------------- 1 | CFBundleURLTypes 2 | 3 | 4 | CFBundleURLName 5 | Dat Link 6 | CFBundleURLSchemes 7 | 8 | dat 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /icons/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/icons/dark.png -------------------------------------------------------------------------------- /icons/dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/icons/dark@2x.png -------------------------------------------------------------------------------- /icons/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/icons/white.png -------------------------------------------------------------------------------- /icons/white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/icons/white@2x.png -------------------------------------------------------------------------------- /images/cat-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-1.png -------------------------------------------------------------------------------- /images/cat-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-2.png -------------------------------------------------------------------------------- /images/cat-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-3.png -------------------------------------------------------------------------------- /images/cat-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-4.png -------------------------------------------------------------------------------- /images/cat-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-5.png -------------------------------------------------------------------------------- /images/cat-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-6.png -------------------------------------------------------------------------------- /images/cat-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mafintosh/dat-drop/b50c9ecb3ce26804b3b343e7c72774834115f548/images/cat-7.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 181 | 182 | 183 |
184 |
185 |
186 |
187 | 188 |
189 |
190 |
191 |
192 | 193 |
Drop some files
194 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var hyperdrive = require('hyperdrive') 2 | var discovery = require('discovery-swarm') 3 | var defaults = require('datland-swarm-defaults') 4 | var memdb = require('memdb') 5 | var drop = require('drag-and-drop-files') 6 | var file = require('random-access-file') 7 | var electron = require('electron') 8 | var speedometer = require('speedometer') 9 | var fs = require('fs') 10 | var basename = require('path').basename 11 | 12 | var $ = document.querySelector.bind(document) 13 | var $me = $('#me') 14 | var $network = $('#network') 15 | 16 | var db = memdb() 17 | var drive = hyperdrive(db) 18 | var files = {} 19 | var catLength = 7 20 | var catOffset = Math.floor(Math.random() * catLength) 21 | 22 | drop(document.body, ondrop) 23 | electron.ipcRenderer.on('drop', function (e, files) { 24 | ondrop(files.map(function (path) { 25 | return { 26 | name: basename(path), 27 | path: path 28 | } 29 | })) 30 | }) 31 | 32 | updatePos([]) 33 | 34 | function updateUI (feed, removed) { 35 | var blocks = feed.blocks 36 | var peers = [] 37 | 38 | if (removed && removed.stream && removed.stream.remoteId) { 39 | var $old = $('#friend-' + removed.stream.remoteId.toString('hex')) 40 | if ($old) $old.parentNode.removeChild($old) 41 | } 42 | 43 | for (var i = 0; i < feed.peers.length; i++) { 44 | var have = 0 45 | var peer = feed.peers[i] 46 | 47 | if (!peer.stream || !peer.stream.remoteId) continue 48 | 49 | for (var j = 0; j < blocks; j++) { 50 | if (peer.remoteBitfield.get(j)) have++ 51 | } 52 | 53 | if (!have) continue 54 | 55 | peers.push(peer) 56 | 57 | var id = 'friend-' + peer.stream.remoteId.toString('hex') 58 | var $el = $('#' + id) 59 | 60 | if (!$el) { 61 | if (catOffset === catLength) catOffset = 0 62 | var cat = catOffset++ + 1 63 | var catUrl = 'file://' + __dirname + '/images/cat-' + catOffset + '.png' 64 | var html = ` 65 |
66 |
67 | 68 |
69 |
70 | ` 71 | 72 | $el = document.createElement('div') 73 | $el.innerHTML = html 74 | $el.className = 'friend' 75 | $el.id = id 76 | 77 | $network.appendChild($el) 78 | } 79 | 80 | updateProgressBar($el, have, blocks) 81 | } 82 | 83 | var localHave = 0 84 | for (var i = 0; i < blocks; i++) { 85 | if (feed.bitfield.get(i)) localHave++ 86 | } 87 | 88 | updateProgressBar($me, localHave, blocks) 89 | updatePos(peers) 90 | } 91 | 92 | function updatePos (peers) { 93 | var wid = 40 94 | var q = Math.PI / 2 95 | var friends = peers.length 96 | 97 | var elHei = $network.offsetHeight 98 | var elWid = $network.offsetWidth 99 | var factor = Math.min(elWid, elHei) * 0.8 100 | 101 | for (var i = 0; i < friends; i++) { 102 | var el = $('#friend-' + peers[i].stream.remoteId.toString('hex')) 103 | var offset = (Math.PI - q) / 2 104 | var range = Math.PI + offset + (i + 1) * (q / (friends + 1)) 105 | 106 | el.style.left = Math.floor(Math.floor(elWid / 2) + factor * Math.cos(range) - wid) + 'px' 107 | el.style.top = Math.floor(factor * Math.sin(range) - 3 * wid + factor + elHei - 2 * elHei / 3) + 'px' 108 | } 109 | 110 | $me.style.left = Math.floor(elWid / 2) - 60 + 'px' 111 | $me.style.top = Math.floor(elHei - 3 * 60) + 'px' 112 | } 113 | 114 | function onlink (link) { 115 | var archive = drive.createArchive(link, { 116 | file: function (name) { 117 | return file('/tmp/downloads/' + name) 118 | } 119 | }) 120 | 121 | joinSwarm(archive) 122 | } 123 | 124 | function ondrop (dropped) { 125 | var archive = drive.createArchive({ 126 | live: false, 127 | file: function (name) { 128 | return file(files[name]) 129 | } 130 | }) 131 | 132 | var cnt = dropped.length 133 | var size = 0 134 | var imported = 0 135 | 136 | dropped.forEach(function (file) { // TODO: wont work for dirs ... 137 | size += file.size 138 | }) 139 | 140 | archive.open(loop) 141 | 142 | function loop () { 143 | var file = dropped.shift() 144 | if (!file) return finalize() 145 | 146 | files[file.name] = file.path 147 | 148 | var ws = archive.createFileWriteStream({type: 'file', name: file.name}, {indexing: true}) 149 | var rs = fs.createReadStream(file.path) 150 | 151 | rs.pipe(ws).on('finish', loop) 152 | rs.on('data', onprogress) 153 | } 154 | 155 | function onprogress (data) { 156 | imported += data.length 157 | updateProgressBar($me, imported, size) 158 | } 159 | 160 | function finalize () { 161 | archive.finalize(function () { 162 | joinSwarm(archive) 163 | }) 164 | } 165 | } 166 | 167 | function joinSwarm (archive) { 168 | archive.open(function () { 169 | archive.content.on('upload', function (block, data, peer) { 170 | peer.uploadSpeed(data.length) 171 | }) 172 | 173 | archive.content.on('download', function (block, data, peer) { 174 | peer.downloadSpeed(data.length) 175 | }) 176 | 177 | archive.content.on('peer-add', function (peer) { 178 | peer.downloadSpeed = speedometer() 179 | peer.uploadSpeed = speedometer() 180 | updateUI(archive.content) 181 | }) 182 | 183 | archive.content.on('peer-remove', function (peer) { 184 | updateUI(archive.content, peer) 185 | }) 186 | 187 | setInterval(update, 1000) 188 | update() 189 | 190 | function update () { 191 | updateUI(archive.content) 192 | } 193 | }) 194 | 195 | replicate(archive) 196 | $('#status').innerHTML = 'dat://' + archive.key.toString('hex') + '' 197 | } 198 | 199 | function updateProgressBar ($el, fetched, total) { 200 | if (!total) return 201 | $el.querySelector('.dat-progress-circle').style.animationDelay = -(100 * fetched / total) + 's' 202 | if (fetched === total) $el.classList.add('bounce-once') 203 | } 204 | 205 | function replicate (archive) { 206 | var swarm = discovery(defaults({ 207 | hash: false, 208 | stream: function () { 209 | return archive.replicate() 210 | } 211 | })) 212 | 213 | swarm.join(archive.discoveryKey) 214 | swarm.once('error', function () { 215 | swarm.listen(0) 216 | }) 217 | 218 | swarm.listen(3282) 219 | } 220 | 221 | // onlink('1626c054742f8437c3f4a48f80c848897dd2c535b310566cdb8e6b1211010852') 222 | 223 | document.addEventListener('paste', function (e) { 224 | onlink(e.clipboardData.getData('text').trim().split('/').pop()) 225 | }) 226 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dat-drop", 3 | "version": "0.0.0", 4 | "description": "Simplest tool to share files with friends", 5 | "main": "index.js", 6 | "dependencies": { 7 | "datland-swarm-defaults": "^1.0.2", 8 | "discovery-swarm": "^4.0.2", 9 | "drag-and-drop-files": "0.0.1", 10 | "electron-prebuilt": "1.1.3", 11 | "hyperdrive": "^7.1.1", 12 | "memdb": "^1.3.1", 13 | "random-access-file": "^1.3.0", 14 | "speedometer": "^1.0.0" 15 | }, 16 | "devDependencies": { 17 | "electron-packager": "^7.4.0" 18 | }, 19 | "scripts": { 20 | "start": "electron app.js", 21 | "rebuild": "npm rebuild --runtime=electron --target=1.1.3 --disturl=https://atom.io/download/atom-shell --abi=48", 22 | "package": "electron-packager . --platform=darwin --arch=x64 --out=dist/ --extend-info extend.plist --app-bundle-id=com.drop.dat" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/mafintosh/dat-drop.git" 27 | }, 28 | "author": "Mathias Buus (@mafintosh)", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/mafintosh/dat-drop/issues" 32 | }, 33 | "homepage": "https://github.com/mafintosh/dat-drop" 34 | } 35 | --------------------------------------------------------------------------------