added blob 'checkout' on open in new window

This commit is contained in:
Paul Frazee 2015-06-25 12:58:41 -05:00
parent 616af83706
commit 93184f5b69
4 changed files with 110 additions and 39 deletions

View File

@ -1,26 +1,26 @@
var app = require('app') var app = require('app')
var path = require('path')
var Tray = require('tray')
var Menu = require('menu') var Menu = require('menu')
var shell = require('shell') var shell = require('shell')
var BrowserWindow = require('browser-window') var BrowserWindow = require('browser-window')
var path = require('path')
var config = require('ssb-config') var config = require('ssb-config')
var toPath = require('multiblob/util').toPath
// Report crashes to our server. // Report crashes to our server.
//require('crash-reporter').start(); //require('crash-reporter').start();
var tray
var mainWindow var mainWindow
app.on('ready', function ready () { app.on('ready', function ready () {
// setup blobs
var blobs_dir = path.join(config.path, 'blobs') var blobs_dir = path.join(config.path, 'blobs')
var downloads_dir = app.getPath('userDesktop')
var blobs = require('./lib/blobs')(blobs_dir, downloads_dir)
// start sbot // start sbot
require('scuttlebot').init(config, function (err, sbot) { require('scuttlebot').init(config, function (err, sbot) {
// register protocols // register protocols
require('protocol').registerProtocol('blob', require('./lib/blob-protocol')(config)) require('protocol').registerProtocol('blob', blobs.protocol)
// open the web app // open the web app
mainWindow = new BrowserWindow({width: 1000, height: 720}) mainWindow = new BrowserWindow({width: 1000, height: 720})
@ -32,8 +32,17 @@ app.on('ready', function ready () {
e.preventDefault() // hell naw e.preventDefault() // hell naw
if (url.indexOf('blob:') === 0) { if (url.indexOf('blob:') === 0) {
// open the file // open the file
var id = url.split(':')[1] blobs.checkout(url, function (err, path) {
shell.openItem(toPath(blobs_dir, id)) if (err) {
if (err.badUrl)
alert('Error: Not a valid file reference')
else if (err.notFound)
alert('Error: This file has not yet been synced. Please try again soon.') // :TODO: show 'search' window
else
console.log(err) // :TODO: something nicer
} else
shell.openItem(path)
})
} else { } else {
// open in the browser // open in the browser
shell.openExternal(url) shell.openExternal(url)
@ -49,24 +58,5 @@ app.on('ready', function ready () {
// ] // ]
// }])) // }]))
// setup tray icon
tray = new Tray(__dirname+'/icon.png')
tray.setContextMenu(Menu.buildFromTemplate([
// { label: 'Open Web App', click: onopen },
{ label: 'Quit', click: onquit }
]))
tray.setToolTip('Secure Scuttlebutt: Running on port 8008')
// tray.on('double-clicked', onopen)
// menu handlers
function onopen () {
shell.openExternal('http://localhost:8008')
}
function onquit () {
tray = null
sbot.close()
process.exit()
}
}) })
}); });

View File

@ -1,13 +0,0 @@
var protocol = require('protocol')
var path = require('path')
var toPath = require('multiblob/util').toPath
module.exports = function (config) {
var dir = path.join(config.path, 'blobs')
return function (request) {
var id = request.url.split(':')[1]
if (request.method == 'GET' && id) {
return new protocol.RequestFileJob(toPath(dir, id))
}
}
}

93
app/lib/blobs.js Normal file
View File

@ -0,0 +1,93 @@
var path = require('path')
var multicb = require('multicb')
var toPath = require('multiblob/util').toPath
var querystring = require('querystring')
var fs = require('fs')
// blob url parser
var re = /^blob:([a-z0-9\+\/=]+\.blake2s)\??(.*)$/i
var url_parse =
module.exports.url_parse = function (str) {
var parts = re.exec(str)
if (parts)
return { hash: parts[1], qs: querystring.parse(parts[2]) }
}
// blob url builder
var url_stringify =
module.exports.url_stringify = function (hash, qs) {
var url = 'blob:'+hash
if (qs && typeof qs == 'object')
url += '?' + querystring.stringify(qs)
return url
}
module.exports = function (blobs_dir, checkout_dir) {
return {
// behavior for the blob: protocol
protocol: function (request) {
var protocol = require('protocol') // have to require here, doing so before app:ready causes errors
// simple fetch
var parsed = url_parse(request.url)
if (request.method == 'GET' && parsed) {
return new protocol.RequestFileJob(toPath(blobs_dir, parsed.hash))
}
},
// copy file from blobs into given dir with nice name
checkout: function (url, cb) {
var parsed = url_parse(url)
if (!parsed)
return cb({ badUrl: true })
var filename = parsed.qs.name || parsed.qs.filename || parsed.hash
// check if we have the blob, at the same time find an available filename
var done = multicb({ pluck: 1 })
fs.stat(toPath(blobs_dir, parsed.hash), done())
findFreeCheckoutPath(filename, done())
done(function (err, res) {
if (!res[0])
return cb({ notFound: true })
// copy the file
var src = toPath(blobs_dir, parsed.hash)
var dst = res[1]
var read = fs.createReadStream(src)
var write = fs.createWriteStream(dst)
read.on('error', done)
write.on('error', done)
write.on('close', done)
read.pipe(write)
function done (err) {
cb && cb(err, dst)
cb = null
}
})
}
}
// helper to create a filename in checkout_dir that isnt already in use
function findFreeCheckoutPath (filename, cb) {
var n = 1
var parsed = path.parse(filename)
next()
function gen () {
var name = parsed.name
if (n !== 1) name += ' ('+n+')'
name += parsed.ext
n++
return path.join(checkout_dir, name)
}
function next () {
var filepath = gen()
fs.stat(filepath, function (err, stat) {
if (!stat)
return cb(null, filepath)
next()
})
}
}
}

View File

@ -26,6 +26,7 @@
}, },
"dependencies": { "dependencies": {
"multiblob": "^1.4.3", "multiblob": "^1.4.3",
"multicb": "^1.1.0",
"scuttlebot": "^4.2.3", "scuttlebot": "^4.2.3",
"ssb-config": "^1.0.3" "ssb-config": "^1.0.3"
} }