secure-scuttlebot classic
at main 4.3 kB view raw
1'use strict' 2var h = require('hyperscript') 3var u = require('../util') 4var suggest = require('suggest-box') 5var mentions = require('ssb-mentions') 6var lightbox = require('hyperlightbox') 7var cont = require('cont') 8 9//var plugs = require('../plugs') 10//var suggest_mentions= plugs.asyncConcat(exports.suggest_mentions = []) 11//var publish = plugs.first(exports.sbot_publish = []) 12//var message_content = plugs.first(exports.message_content = []) 13//var message_confirm = plugs.first(exports.message_confirm = []) 14//var file_input = plugs.first(exports.file_input = []) 15 16exports.needs = { 17 suggest_mentions: 'map', //<-- THIS MUST BE REWRITTEN 18 publish: 'first', 19 message_content: 'first', 20 message_confirm: 'first', 21 file_input: 'first' 22} 23 24exports.gives = 'message_compose' 25 26function id (e) { return e } 27 28/* 29 opts can take 30 31 placeholder: string. placeholder text, defaults to "Write a message" 32 prepublish: function. called before publishing a message. 33 shrink: boolean. set to false, to make composer not shrink (or hide controls) when unfocused. 34*/ 35 36exports.create = function (api) { 37 38 return function (meta, opts, cb) { 39 if('function' === typeof cb) { 40 if('function' === typeof opts) 41 opts = {prepublish: opts} 42 } 43 44 if(!opts) opts = {} 45 opts.prepublish = opts.prepublish || id 46 47 var accessories 48 meta = meta || {} 49 if(!meta.type) throw new Error('message must have type') 50 var ta = h('textarea', { 51 placeholder: opts.placeholder || 'Write a message', 52 style: {height: opts.shrink === false ? '200px' : ''} 53 }) 54 55 if(opts.shrink !== false) { 56 var blur 57 ta.addEventListener('focus', function () { 58 clearTimeout(blur) 59 if(!ta.value) { 60 ta.style.height = '200px' 61 } 62 accessories.style.display = 'block' 63 }) 64 ta.addEventListener('blur', function () { 65 //don't shrink right away, so there is time 66 //to click the publish button. 67 clearTimeout(blur) 68 blur = setTimeout(function () { 69 if(ta.value) return 70 ta.style.height = '50px' 71 accessories.style.display = 'none' 72 }, 200) 73 }) 74 } 75 76 ta.addEventListener('keydown', function (ev) { 77 if(ev.keyCode === 13 && ev.ctrlKey) publish() 78 }) 79 80 var files = [] 81 var filesById = {} 82 83 function publish() { 84 publishBtn.disabled = true 85 var content 86 try { 87 content = JSON.parse(ta.value) 88 } catch (err) { 89 meta.text = ta.value 90 meta.mentions = mentions(ta.value).map(function (mention) { 91 // merge markdown-detected mention with file info 92 var file = filesById[mention.link] 93 if (file) { 94 if (file.type) mention.type = file.type 95 if (file.size) mention.size = file.size 96 } 97 return mention 98 }) 99 try { 100 meta = opts.prepublish(meta) 101 } catch (err) { 102 publishBtn.disabled = false 103 if (cb) cb(err) 104 else alert(err.message) 105 } 106 return api.message_confirm(meta, done) 107 } 108 109 api.message_confirm(content, done) 110 111 function done (err, msg) { 112 publishBtn.disabled = false 113 if(err) return alert(err.stack) 114 else if (msg) ta.value = '' 115 116 if (cb) cb(err, msg) 117 } 118 } 119 120 121 var publishBtn = h('button', 'Publish', {onclick: publish}) 122 var composer = 123 h('div.compose', h('div.column', ta, 124 accessories = h('div.row.compose__controls', 125 //hidden until you focus the textarea 126 {style: {display: opts.shrink === false ? '' : 'none'}}, 127 api.file_input(function (file) { 128 files.push(file) 129 filesById[file.link] = file 130 131 var embed = file.type.indexOf('image/') === 0 ? '!' : '' 132 ta.value += embed + '['+file.name+']('+file.link+')' 133 console.log('added:', file) 134 }), 135 publishBtn) 136 ) 137 ) 138 139 suggest(ta, function (name, cb) { 140 cont.para(api.suggest_mentions(name)) 141 (function (err, ary) { 142 cb(null, ary.reduce(function (a, b) { 143 if(!b) return a 144 return a.concat(b) 145 }, [])) 146 }) 147 }, {}) 148 149 return composer 150 151 } 152 153} 154 155