2015-09-23 05:44:28 +11:00
'use strict'
var h = require ( 'hyperscript' )
var o = require ( 'observable' )
var schemas = require ( 'ssb-msg-schemas' )
var mlib = require ( 'ssb-msgs' )
var pull = require ( 'pull-stream' )
var pushable = require ( 'pull-pushable' )
var createHash = require ( 'multiblob/util' ) . createHash
var suggestBox = require ( 'suggest-box' )
var toBuffer = require ( 'blob-to-buffer' )
var app = require ( '../app' )
var ui = require ( '../ui' )
var modals = require ( '../ui/modals' )
var com = require ( './index' )
var mentionslib = require ( '../mentions' )
var videoOpts = {
optional : [
{ minHeight : 150 } ,
{ maxHeight : 150 } ,
{ minWidth : 300 } ,
{ maxWidth : 300 }
]
}
module . exports = function ( rootMsg , branchMsg , opts ) {
opts = opts || { }
var blob
var recordInterval
var encoder = new Whammy . Video ( 10 )
var countdown = o ( 0 )
// markup
var canvas = h ( 'canvas' )
var context = canvas . getContext ( '2d' )
var invideo = h ( 'video' )
var outvideo = h ( 'video.hide' , { autoplay : true , loop : true } )
var textarea = h ( 'textarea.form-control' , {
name : 'text' ,
placeholder : 'Add a message (optional)' ,
rows : 6
} )
var publishBtn = h ( 'button.btn.btn-primary.pull-right.hidden' , { onclick : onpublish } , 'Publish' )
var form = h ( 'form.webcam-giffer-form' ,
h ( '.webcam-giffer-form-videos' , { onmousedown : onmousedown } ,
o . transform ( countdown , function ( c ) {
if ( ! c )
return ''
return h ( '.countdown' , c )
} ) ,
invideo ,
outvideo ,
h ( 'br' ) ,
h ( 'a.btn.btn-3d' , { onclick : onrecord ( 1 ) } , com . icon ( 'record' ) , ' Record 1s' ) , ' ' ,
h ( 'a.btn.btn-3d' , { onclick : onrecord ( 2 ) } , '2s' ) , ' ' ,
h ( 'a.btn.btn-3d' , { onclick : onrecord ( 3 ) , style : 'margin-right: 10px' } , '3s' ) ,
h ( 'a.text-muted' , { href : '#' , onclick : onreset } , com . icon ( 'repeat' ) , ' Reset' )
) ,
h ( '.webcam-giffer-form-ctrls' , textarea , publishBtn )
)
suggestBox ( textarea , app . suggestOptions )
function disable ( ) {
publishBtn . classList . add ( 'hidden' )
}
function enable ( ) {
publishBtn . classList . remove ( 'hidden' )
}
// handlers
function onmousedown ( e ) {
if ( e . target . tagName == 'VIDEO' ) {
e . preventDefault ( )
startRecording ( )
document . addEventListener ( 'mouseup' , onmouseup )
}
}
function onmouseup ( e ) {
e . preventDefault ( )
stopRecording ( )
document . removeEventListener ( 'mouseup' , onmouseup )
}
function onrecord ( seconds ) {
return function ( e ) {
e . preventDefault ( )
startRecordingAfter ( 2 , seconds )
}
}
function onreset ( e ) {
e && e . preventDefault ( )
encoder . frames = [ ]
invideo . classList . remove ( 'hide' )
outvideo . classList . add ( 'hide' )
disable ( )
}
function onpublish ( e ) {
e . preventDefault ( )
var text = textarea . value || ''
if ( ! blob )
return
disable ( )
ui . pleaseWait ( true )
// abort if the rootMsg wasnt decryptable
if ( rootMsg && typeof rootMsg . value . content == 'string' ) {
ui . pleaseWait ( false )
ui . notice ( 'danger' , 'Unable to decrypt rootMsg message' )
enable ( )
return
}
function onerr ( err ) {
ui . setStatus ( null )
ui . pleaseWait ( false )
enable ( )
modals . error ( 'Error While Publishing' , err , 'This error occurred while trying to upload a webcam video to the blobstore.' )
}
// upload blob to sbot
var hasher = createHash ( 'sha256' )
var ps = pushable ( )
pull (
ps ,
hasher ,
app . ssb . blobs . add ( function ( err ) {
if ( err ) return onerr ( err )
afterUpload ( )
} )
)
toBuffer ( blob , function ( err , buffer ) {
if ( err ) return onerr ( err )
ps . push ( buffer )
ps . end ( )
} )
function afterUpload ( ) {
// prepend the image-embed ot the text
text = '![webcam.webm](&' + hasher . digest + ')\n\n' + text
console . log ( 'posting' , text )
// prep text
mentionslib . extract ( text , function ( err , mentions ) {
if ( err ) {
ui . setStatus ( null )
ui . pleaseWait ( false )
enable ( )
if ( err . conflict )
modals . error ( 'Error While Publishing' , 'You follow multiple people with the name "' + err . name + '." Go to the homepage to resolve this before publishing.' )
else
modals . error ( 'Error While Publishing' , err , 'This error occurred while trying to extract the mentions from the text of a webcam post.' )
return
}
// get encryption recipients from rootMsg
var recps
try {
if ( Array . isArray ( rootMsg . value . content . recps ) ) {
recps = mlib . links ( rootMsg . value . content . recps )
. map ( function ( recp ) { return recp . link } )
. filter ( Boolean )
}
} catch ( e ) { }
// post
var post = schemas . post ( text , rootMsg && rootMsg . key , branchMsg && branchMsg . key , mentions , recps )
if ( recps )
app . ssb . private . publish ( post , recps , published )
else
app . ssb . publish ( post , published )
function published ( err , msg ) {
ui . setStatus ( null )
enable ( )
ui . pleaseWait ( false )
if ( err ) modals . error ( 'Error While Publishing' , err , 'This error occurred while trying to post a webcam video.' )
else {
textarea . value = ''
app . ssb . patchwork . subscribe ( msg . key )
app . ssb . patchwork . markRead ( msg . key )
opts && opts . onpost && opts . onpost ( msg )
onreset ( )
}
}
} )
}
}
// init webcam
navigator . webkitGetUserMedia ( { video : videoOpts , audio : false } , function ( stream ) {
invideo . src = window . URL . createObjectURL ( stream )
invideo . onloadedmetadata = function ( ) { invideo . play ( ) }
ui . onTeardown ( function ( ) {
stream . stop ( )
} )
} , function ( err ) {
modals . error ( 'Failed to Access Webcam' , err )
} )
// recording functions
function startRecordingAfter ( c , seconds ) {
// show input stream
invideo . classList . remove ( 'hide' )
outvideo . classList . add ( 'hide' )
// run countdown
countdown ( c )
var i = setInterval ( function ( ) {
countdown ( countdown ( ) - 1 )
if ( countdown ( ) === 0 ) {
clearInterval ( i )
startRecording ( seconds )
}
} , 1000 )
}
function startRecording ( seconds ) {
// show input stream
invideo . classList . remove ( 'hide' )
outvideo . classList . add ( 'hide' )
// add 'recording' border
invideo . classList . add ( 'recording' )
// start capture
recordInterval = setInterval ( captureFrame , 1000 / 10 )
// captureFrame()
if ( seconds )
setTimeout ( stopRecording , seconds * 1000 )
}
function captureFrame ( ) {
context . drawImage ( invideo , 0 , 0 , 300 , 150 )
encoder . add ( canvas )
}
function stopRecording ( ) {
// stop capture
clearInterval ( recordInterval )
// remove 'recording' border
invideo . classList . remove ( 'recording' )
// produce output
2015-09-30 04:50:01 +11:00
if ( encoder . frames && encoder . frames . length ) {
blob = encoder . compile ( )
console . log ( 'Webm video encoded:' , blob . size , 'bytes' )
outvideo . src = URL . createObjectURL ( blob , 'video/webm' )
// show output stream
invideo . classList . add ( 'hide' )
outvideo . classList . remove ( 'hide' )
} else {
// show input stream
invideo . classList . remove ( 'hide' )
outvideo . classList . add ( 'hide' )
}
2015-09-23 05:44:28 +11:00
enable ( )
}
return form
}