git ssb

16+

Dominic / patchbay



Tree: c14e98624b1ae5d90235af8556d3f3d82510130d

Files: c14e98624b1ae5d90235af8556d3f3d82510130d / modules_basic / compose.js

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

Built with git-ssb-web