git ssb

16+

Dominic / patchbay



Tree: 52a6d8a8df089abd1131e52adf418fdf6595f98a

Files: 52a6d8a8df089abd1131e52adf418fdf6595f98a / modules_basic / compose.js

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

Built with git-ssb-web