2015-09-23 05:44:28 +11:00
'use strict'
var h = require ( 'hyperscript' )
var suggestBox = require ( 'suggest-box' )
var schemas = require ( 'ssb-msg-schemas' )
var refs = require ( 'ssb-ref' )
var createHash = require ( 'multiblob/util' ) . createHash
var pull = require ( 'pull-stream' )
var pushable = require ( 'pull-pushable' )
var app = require ( '../app' )
var ui = require ( '../ui' )
var modals = require ( '../ui/modals' )
var com = require ( './index' )
var util = require ( '../util' )
var markdown = require ( '../markdown' )
var mentionslib = require ( '../mentions' )
var social = require ( '../social-graph' )
2015-09-30 03:03:32 +11:00
module . exports = function ( opts , h2 ) {
h = h2 || h
2015-09-23 05:44:28 +11:00
var recipients = [ ]
var placeholder = ( opts && opts . placeholder ) ? opts . placeholder : ''
// make sure there are no name conflicts first
var conflicts = [ ]
for ( var k in app . actionItems ) {
var item = app . actionItems [ k ]
if ( item . type == 'name-conflict' ) {
conflicts . push ( h ( '.note.warning' ,
h ( 'h3' , 'Heads up!' ) ,
h ( 'p' , 'You are following more than one user named "' + item . name + '." You need to rename one of them before you send secret messages, to avoid confusion.' ) ,
h ( 'ul.list-inline' , item . ids . map ( function ( id ) { return h ( 'li' , com . userImg ( id ) , ' ' , com . user ( id ) ) } ) )
) )
}
}
if ( conflicts . length )
return h ( '.notifications' , { style : 'margin-top: 24px' } , conflicts )
// markup
var recpInput = h ( 'input' , { onsuggestselect : onSelectRecipient , onkeydown : onRecpInputKeydown } )
var recipientsEl = h ( '.pm-form-recipients' , h ( 'span.recp-label' , 'To' ) , recpInput )
var textarea = h ( 'textarea' , { name : 'text' , placeholder : placeholder , onkeyup : onTextChange } )
var postBtn = h ( 'button.postbtn.btn' , { disabled : true } , 'Send' )
suggestBox ( textarea , app . suggestOptions )
suggestBox ( recpInput , { any : app . suggestOptions [ '@' ] } , { cls : 'msg-recipients' } )
renderRecpList ( )
if ( opts && opts . recipients )
opts . recipients . forEach ( addRecp )
var form = h ( 'form.pm-form' , { onsubmit : post } ,
recipientsEl ,
h ( '.pm-form-textarea' , textarea ) ,
h ( '.pm-form-attachments' , postBtn )
)
function disable ( ) {
postBtn . setAttribute ( 'disabled' , true )
}
function enable ( ) {
postBtn . removeAttribute ( 'disabled' )
}
function renderRecpList ( ) {
// remove all .recp
Array . prototype . forEach . call ( recipientsEl . querySelectorAll ( '.recp' ) , function ( el ) {
recipientsEl . removeChild ( el )
} )
// render
recipients . forEach ( function ( id ) {
recipientsEl . insertBefore ( h ( '.recp' ,
com . icon ( 'lock' ) ,
' ' ,
com . userName ( id ) ,
' ' ,
h ( 'a' , { href : '#' , onclick : onRemoveRecipient , 'data-id' : id , innerHTML : '×' , tabIndex : '-1' } )
) , recpInput )
} )
resizeTextarea ( )
}
// handlers
function onTextChange ( e ) {
if ( recipients . length && textarea . value . trim ( ) )
enable ( )
else
disable ( )
}
function addRecp ( id ) {
// enforce limit
if ( recipients . length >= 7 ) {
ui . notice ( 'warning' , 'Cannot add @' + com . userName ( id ) + ' - You have reached the limit of 7 recipients on a Secret Message.' )
recpInput . value = ''
return
}
// warn if the recipient doesnt follow the current user
if ( id !== app . user . id && ! social . follows ( id , app . user . id ) )
ui . notice ( 'warning' , 'Warning: @' + com . userName ( id ) + ' does not follow you, and may not receive your message.' )
// remove if already exists (we'll push to end of list so user sees its there)
var i = recipients . indexOf ( id )
if ( i !== - 1 )
recipients . splice ( i , 1 )
// add, render
recipients . push ( id )
recpInput . value = ''
renderRecpList ( )
}
function onSelectRecipient ( e ) {
addRecp ( e . detail . id )
}
function onRemoveRecipient ( e ) {
e . preventDefault ( )
var i = recipients . indexOf ( e . target . dataset . id )
if ( i !== - 1 ) {
recipients . splice ( i , 1 )
renderRecpList ( )
recpInput . focus ( )
}
}
function onRecpInputKeydown ( e ) {
// backspace on an empty field?
if ( e . keyCode == 8 && recpInput . value == '' && recipients . length ) {
recipients . pop ( )
renderRecpList ( )
}
}
// dynamically sizes the textarea based on available space
// (no css method, including flexbox, would really nail this one)
function resizeTextarea ( ) {
try {
var height = 400 - 4
height -= recipientsEl . getClientRects ( ) [ 0 ] . height
height -= form . querySelector ( '.pm-form-attachments' ) . getClientRects ( ) [ 0 ] . height
textarea . style . height = height + 'px'
} catch ( e ) {
// ignore, probably havent rendered yet
}
}
function post ( e ) {
e . preventDefault ( )
var text = textarea . value
if ( ! text . trim ( ) )
return
disable ( )
ui . pleaseWait ( true )
// 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 occured while trying to extract the mentions from a secret message text.' )
return
}
// make sure the user is in the recipients
if ( recipients . indexOf ( app . user . id ) === - 1 )
recipients . push ( app . user . id )
// list recipients with their names
var recps = recipients . map ( function ( id ) {
return { link : id , name : com . userName ( id ) }
} )
// publish
var post = schemas . post ( text , null , null , mentions , recps )
app . ssb . private . publish ( post , recipients , function ( err , msg ) {
ui . setStatus ( null )
enable ( )
ui . pleaseWait ( false )
if ( err ) modals . error ( 'Error While Publishing' , err , 'This error occured while trying to private-publish a new secret message.' )
else {
app . ssb . patchwork . subscribe ( msg . key )
app . ssb . patchwork . markRead ( msg . key )
opts && opts . onpost && opts . onpost ( msg )
}
} )
} )
}
return form
}