git ssb

16+

Dominic / patchbay



Tree: 7478b5388306a177f85de2b6a0c3bcedf8635c87

Files: 7478b5388306a177f85de2b6a0c3bcedf8635c87 / modules_basic / compose.js

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

Built with git-ssb-web