Browse Source

added blob 'checkout' on open in new window

Paul Frazee 5 years ago
parent
commit
93184f5b69
4 changed files with 110 additions and 39 deletions
  1. 16
    26
      app/index.js
  2. 0
    13
      app/lib/blob-protocol.js
  3. 93
    0
      app/lib/blobs.js
  4. 1
    0
      package.json

+ 16
- 26
app/index.js View File

@@ -1,26 +1,26 @@
1 1
 var app = require('app')
2
-var path = require('path')
3
-var Tray = require('tray')
4 2
 var Menu = require('menu')
5 3
 var shell = require('shell')
6 4
 var BrowserWindow = require('browser-window')
5
+var path = require('path')
7 6
 
8 7
 var config = require('ssb-config') 
9
-var toPath = require('multiblob/util').toPath
10 8
 
11 9
 // Report crashes to our server.
12 10
 //require('crash-reporter').start();
13 11
 
14
-var tray
15 12
 var mainWindow
16 13
 
17 14
 app.on('ready', function ready () {
15
+  // setup blobs
18 16
   var blobs_dir = path.join(config.path, 'blobs')
17
+  var downloads_dir = app.getPath('userDesktop')
18
+  var blobs = require('./lib/blobs')(blobs_dir, downloads_dir)
19 19
 
20 20
   // start sbot
21 21
   require('scuttlebot').init(config, function (err, sbot) {
22 22
     // register protocols
23
-    require('protocol').registerProtocol('blob', require('./lib/blob-protocol')(config))
23
+    require('protocol').registerProtocol('blob', blobs.protocol)
24 24
 
25 25
     // open the web app
26 26
     mainWindow = new BrowserWindow({width: 1000, height: 720})
@@ -32,8 +32,17 @@ app.on('ready', function ready () {
32 32
       e.preventDefault() // hell naw
33 33
       if (url.indexOf('blob:') === 0) {
34 34
         // open the file
35
-        var id = url.split(':')[1]
36
-        shell.openItem(toPath(blobs_dir, id))
35
+        blobs.checkout(url, function (err, path) {
36
+          if (err) {
37
+            if (err.badUrl)
38
+              alert('Error: Not a valid file reference')
39
+            else if (err.notFound)
40
+              alert('Error: This file has not yet been synced. Please try again soon.') // :TODO: show 'search' window
41
+            else
42
+              console.log(err) // :TODO: something nicer
43
+          } else
44
+            shell.openItem(path)
45
+        })
37 46
       } else {
38 47
         // open in the browser
39 48
         shell.openExternal(url)
@@ -49,24 +58,5 @@ app.on('ready', function ready () {
49 58
     //   ]
50 59
     // }]))
51 60
 
52
-    // setup tray icon
53
-    tray = new Tray(__dirname+'/icon.png')
54
-    tray.setContextMenu(Menu.buildFromTemplate([
55
-      // { label: 'Open Web App', click: onopen },
56
-      { label: 'Quit', click: onquit }
57
-    ]))
58
-    tray.setToolTip('Secure Scuttlebutt: Running on port 8008')
59
-    // tray.on('double-clicked', onopen)
60
-
61
-    // menu handlers
62
-    function onopen () {
63
-      shell.openExternal('http://localhost:8008')
64
-    }
65
-    function onquit () {
66
-      tray = null
67
-      sbot.close()
68
-      process.exit()
69
-    }
70
-
71 61
   })
72 62
 });

+ 0
- 13
app/lib/blob-protocol.js View File

@@ -1,13 +0,0 @@
1
-var protocol = require('protocol')
2
-var path = require('path')
3
-var toPath = require('multiblob/util').toPath
4
-
5
-module.exports = function (config) {
6
-  var dir = path.join(config.path, 'blobs')
7
-  return function (request) {
8
-    var id = request.url.split(':')[1]
9
-    if (request.method == 'GET' && id) {
10
-      return new protocol.RequestFileJob(toPath(dir, id))
11
-    }
12
-  }
13
-}

+ 93
- 0
app/lib/blobs.js View File

@@ -0,0 +1,93 @@
1
+var path = require('path')
2
+var multicb = require('multicb')
3
+var toPath = require('multiblob/util').toPath
4
+var querystring = require('querystring')
5
+var fs = require('fs')
6
+
7
+// blob url parser
8
+var re = /^blob:([a-z0-9\+\/=]+\.blake2s)\??(.*)$/i
9
+var url_parse =
10
+module.exports.url_parse = function (str) {
11
+  var parts = re.exec(str)
12
+  if (parts)
13
+    return { hash: parts[1], qs: querystring.parse(parts[2]) }
14
+}
15
+
16
+// blob url builder
17
+var url_stringify =
18
+module.exports.url_stringify = function (hash, qs) {
19
+  var url = 'blob:'+hash
20
+  if (qs && typeof qs == 'object')
21
+    url += '?' + querystring.stringify(qs)
22
+  return url
23
+}
24
+
25
+module.exports = function (blobs_dir, checkout_dir) {
26
+  return {
27
+    // behavior for the blob: protocol
28
+    protocol: function (request) {
29
+      var protocol = require('protocol') // have to require here, doing so before app:ready causes errors
30
+      // simple fetch
31
+      var parsed = url_parse(request.url)
32
+      if (request.method == 'GET' && parsed) {
33
+        return new protocol.RequestFileJob(toPath(blobs_dir, parsed.hash))
34
+      }
35
+    },
36
+
37
+    // copy file from blobs into given dir with nice name
38
+    checkout: function (url, cb) {
39
+      var parsed = url_parse(url)
40
+      if (!parsed)
41
+        return cb({ badUrl: true })
42
+      
43
+      var filename = parsed.qs.name || parsed.qs.filename || parsed.hash
44
+
45
+      // check if we have the blob, at the same time find an available filename
46
+      var done = multicb({ pluck: 1 })
47
+      fs.stat(toPath(blobs_dir, parsed.hash), done())
48
+      findFreeCheckoutPath(filename, done())
49
+      done(function (err, res) {
50
+        if (!res[0])
51
+          return cb({ notFound: true })
52
+
53
+        // copy the file
54
+        var src = toPath(blobs_dir, parsed.hash)
55
+        var dst = res[1]
56
+        var read = fs.createReadStream(src)
57
+        var write = fs.createWriteStream(dst)
58
+        read.on('error', done)
59
+        write.on('error', done)
60
+        write.on('close', done)
61
+        read.pipe(write)
62
+        function done (err) {
63
+          cb && cb(err, dst)
64
+          cb = null
65
+        }
66
+      })
67
+    }
68
+  }
69
+
70
+  // helper to create a filename in checkout_dir that isnt already in use
71
+  function findFreeCheckoutPath (filename, cb) {
72
+    var n = 1
73
+    var parsed = path.parse(filename)
74
+    next()
75
+
76
+    function gen () {
77
+      var name = parsed.name
78
+      if (n !== 1) name += ' ('+n+')'
79
+      name += parsed.ext
80
+      n++
81
+      return path.join(checkout_dir, name)
82
+    }
83
+
84
+    function next () {
85
+      var filepath = gen()
86
+      fs.stat(filepath, function (err, stat) {
87
+        if (!stat)
88
+          return cb(null, filepath)
89
+        next()
90
+      })
91
+    }
92
+  }
93
+}

+ 1
- 0
package.json View File

@@ -26,6 +26,7 @@
26 26
   },
27 27
   "dependencies": {
28 28
     "multiblob": "^1.4.3",
29
+    "multicb": "^1.1.0",
29 30
     "scuttlebot": "^4.2.3",
30 31
     "ssb-config": "^1.0.3"
31 32
   }

Loading…
Cancel
Save