202 lines
6.0 KiB
JavaScript
202 lines
6.0 KiB
JavaScript
'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')
|
|
|
|
module.exports = function (opts, h2) {
|
|
h = h2 || h
|
|
|
|
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
|
|
} |