├── .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 |
--------------------------------------------------------------------------------