git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: 26d9fa8ec162c42e2fa61b44c63952e0f38b38c3

Files: 26d9fa8ec162c42e2fa61b44c63952e0f38b38c3 / modules / message / html / compose.js

4069 bytesRaw
1var h = require('mutant/h')
2var when = require('mutant/when')
3var send = require('mutant/send')
4var resolve = require('mutant/resolve')
5var Value = require('mutant/value')
6var computed = require('mutant/computed')
7var nest = require('depnest')
8var mentions = require('ssb-mentions')
9var extend = require('xtend')
10var addSuggest = require('suggest-box')
11
12exports.needs = nest({
13 'blob.html.input': 'first',
14 'profile.async.suggest': 'first',
15 'channel.async.suggest': 'first',
16 'message.async.publish': 'first',
17 'emoji.sync.names': 'first',
18 'emoji.sync.url': 'first'
19})
20
21exports.gives = nest('message.html.compose')
22
23exports.create = function (api) {
24 return nest('message.html.compose', function ({shrink = true, meta, prepublish, placeholder = 'Write a message'}, cb) {
25 var files = []
26 var filesById = {}
27 var focused = Value(false)
28 var hasContent = Value(false)
29 var getProfileSuggestions = api.profile.async.suggest()
30 var getChannelSuggestions = api.channel.async.suggest()
31
32 var blurTimeout = null
33
34 var expanded = computed([shrink, focused, hasContent], (shrink, focused, hasContent) => {
35 if (!shrink || hasContent) {
36 return true
37 } else {
38 return focused
39 }
40 })
41
42 var textArea = h('textarea', {
43 'ev-input': function () {
44 hasContent.set(!!textArea.value)
45 },
46 'ev-blur': () => {
47 clearTimeout(blurTimeout)
48 blurTimeout = setTimeout(() => focused.set(false), 200)
49 },
50 'ev-focus': send(focused.set, true),
51 placeholder
52 })
53
54 var fileInput = api.blob.html.input(file => {
55 files.push(file)
56 filesById[file.link] = file
57
58 var embed = file.type.indexOf('image/') === 0 ? '!' : ''
59
60 textArea.value += embed + `[${file.name}](${file.link})`
61 console.log('added:', file)
62 })
63
64 fileInput.onclick = function () {
65 hasContent.set(true)
66 }
67
68 var publishBtn = h('button', { 'ev-click': publish }, 'Publish')
69
70 var actions = h('section.actions', [
71 fileInput,
72 publishBtn
73 ])
74
75 var composer = h('Compose', {
76 classList: [
77 when(expanded, '-expanded', '-contracted')
78 ]
79 }, [
80 textArea,
81 actions
82 ])
83
84 addSuggest(textArea, (inputText, cb) => {
85 if (inputText[0] === '@') {
86 cb(null, getProfileSuggestions(inputText.slice(1)))
87 } else if (inputText[0] === '#') {
88 cb(null, getChannelSuggestions(inputText.slice(1)))
89 } else if (inputText[0] === ':') {
90 // suggest emojis
91 var word = inputText.slice(1)
92 if (word[word.length - 1] === ':') {
93 word = word.slice(0, -1)
94 }
95 // TODO: when no emoji typed, list some default ones
96 cb(null, api.emoji.sync.names().filter(function (name) {
97 return name.slice(0, word.length) === word
98 }).slice(0, 100).map(function (emoji) {
99 return {
100 image: api.emoji.sync.url(emoji),
101 title: emoji,
102 subtitle: emoji,
103 value: ':' + emoji + ':'
104 }
105 }))
106 }
107 }, {cls: 'SuggestBox'})
108
109 return composer
110
111 // scoped
112
113 function publish () {
114 publishBtn.disabled = true
115
116 meta = extend(resolve(meta), {
117 text: textArea.value,
118 mentions: mentions(textArea.value).map(mention => {
119 // merge markdown-detected mention with file info
120 var file = filesById[mention.link]
121 if (file) {
122 if (file.type) mention.type = file.type
123 if (file.size) mention.size = file.size
124 }
125 return mention
126 })
127 })
128
129 try {
130 if (typeof prepublish === 'function') {
131 meta = prepublish(meta)
132 }
133 } catch (err) {
134 publishBtn.disabled = false
135 if (cb) cb(err)
136 else throw err
137 }
138
139 return api.message.async.publish(meta, done)
140
141 function done (err, msg) {
142 publishBtn.disabled = false
143 if (err) throw err
144 else if (msg) textArea.value = ''
145 if (cb) cb(err, msg)
146 }
147 }
148 })
149}
150

Built with git-ssb-web