git ssb

16+

Dominic / patchbay



Tree: 558b11e7e152891f436d17180335e54c3701aa6b

Files: 558b11e7e152891f436d17180335e54c3701aa6b / modules_basic / compose.js

4779 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 suggest_channel: 'map',
9 build_suggest_box: 'first',
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 var channelInput = h('input.channel', {
52 placeholder: '#channel',
53 value: meta.channel ? `#${meta.channel}` : '',
54 disabled: meta.channel ? true : false
55 })
56
57 channelInput.addEventListener('keydown', function (e) {
58 console.log(e)
59 if (this.value.startsWith('#') && this.value.length === 1) {
60 this.value = ''
61 return
62 }
63 if (this.value.startsWith('#')) return
64 this.value = `#${this.value}`
65 })
66
67 if(opts.shrink !== false) {
68 var blur
69 textArea.addEventListener('focus', () => {
70 clearTimeout(blur)
71 if(!textArea.value) {
72 composer.className = 'Compose -expanded'
73 }
74 })
75 textArea.addEventListener('blur', () => {
76 //don't shrink right away, so there is time
77 //to click the publish button.
78 clearTimeout(blur)
79 blur = setTimeout(() => {
80 if(textArea.value) return
81 composer.className = 'Compose -contracted'
82 }, 300)
83 })
84 channelInput.addEventListener('focus', () => {
85 clearTimeout(blur)
86 if (!textArea.value) {
87 composer.className = 'Compose -expanded'
88 }
89 })
90 channelInput.addEventListener('blur', () => {
91 clearTimeout(blur)
92 blur = setTimeout(() => {
93 if (textArea.value || channelInput.value) return
94 composer.className = 'Compose -contracted'
95 }, 300)
96 })
97 }
98
99 textArea.addEventListener('keydown', ev => {
100 if(ev.keyCode === 13 && ev.ctrlKey) publish()
101 })
102
103 var files = []
104 var filesById = {}
105
106 function publish() {
107 publishBtn.disabled = true
108 var content
109 try {
110 content = JSON.parse(textArea.value)
111 } catch (err) {
112 meta.text = textArea.value
113 meta.channel = (channelInput.value.startsWith('#') ?
114 channelInput.value.substr(1).trim() : channelInput.value.trim()) || null
115 meta.mentions = mentions(textArea.value).map(mention => {
116 // merge markdown-detected mention with file info
117 var file = filesById[mention.link]
118 if (file) {
119 if (file.type) mention.type = file.type
120 if (file.size) mention.size = file.size
121 }
122 return mention
123 })
124 try {
125 meta = opts.prepublish(meta)
126 } catch (err) {
127 publishBtn.disabled = false
128 if (cb) cb(err)
129 else alert(err.message)
130 }
131 return api.message_confirm(meta, done)
132 }
133
134 api.message_confirm(content, done)
135
136 function done (err, msg) {
137 publishBtn.disabled = false
138 if(err) return alert(err.stack)
139 else if (msg) textArea.value = ''
140
141 if (cb) cb(err, msg)
142 }
143 }
144
145 var fileInput = api.file_input(file => {
146 files.push(file)
147 filesById[file.link] = file
148
149 var embed = file.type.indexOf('image/') === 0 ? '!' : ''
150
151 textArea.value += embed + '['+file.name+']('+file.link+')'
152 composer.className = 'Compose -expanded'
153 console.log('added:', file)
154 })
155 var publishBtn = h('button', {'ev-click': publish}, 'Publish' )
156 var actions = h('section.actions', [
157 fileInput, publishBtn
158 ])
159
160 api.build_suggest_box(textArea, api.suggest_mentions)
161 api.build_suggest_box(channelInput, api.suggest_channel)
162
163 var composer = h('Compose', {
164 className: opts.shrink === false ? '-expanded' : '-contracted'
165 }, [
166 textArea,
167 channelInput,
168 actions
169 ])
170
171
172 return composer
173 }
174
175}
176
177function id (e) { return e }
178

Built with git-ssb-web