app/page/threadNew.jsView |
---|
1 | 1 | const nest = require('depnest') |
2 | | -const { h, Struct, Value, Array: MutantArray, computed, map } = require('mutant') |
| 2 | +const { h, Struct, Value, Array: MutantArray, computed, map, resolve } = require('mutant') |
| 3 | +const suggestBox = require('suggest-box') |
3 | 4 | |
4 | 5 | exports.gives = nest('app.page.threadNew') |
5 | 6 | |
6 | 7 | exports.needs = nest({ |
| 8 | + 'about.async.suggest': 'first', |
7 | 9 | 'about.html.avatar': 'first', |
8 | 10 | 'about.obs.name': 'first', |
9 | 11 | 'app.html.sideNav': 'first', |
10 | 12 | 'app.html.thread': 'first', |
11 | 13 | 'history.sync.push': 'first', |
12 | 14 | 'keys.sync.id': 'first', |
13 | 15 | 'message.html.compose': 'first', |
| 16 | + 'message.sync.unbox': 'first', |
14 | 17 | 'translations.sync.strings': 'first', |
15 | 18 | }) |
16 | 19 | |
17 | 20 | exports.create = (api) => { |
28 | 31 | const strings = api.translations.sync.strings() |
29 | 32 | const myId = api.keys.sync.id() |
30 | 33 | |
31 | 34 | const { feed } = location |
32 | | - const name = api.about.obs.name |
33 | 35 | |
34 | | - const searchInput = Value() |
35 | 36 | const meta = Struct({ |
36 | 37 | type: 'post', |
37 | 38 | recps: MutantArray ([ |
38 | 39 | myId, |
39 | | - { link: feed, name: name(feed) } |
| 40 | + { link: feed, name: resolve(api.about.obs.name(feed)) } |
40 | 41 | ]), |
41 | 42 | subject: Value() |
42 | 43 | }) |
43 | 44 | |
44 | | - const composer = api.message.html.compose( |
45 | | - { meta, shrink: false }, |
46 | | - (err, msg) => api.history.sync.push(err ? err : Object.assign(msg, { feed })) |
47 | | - ) |
48 | | - |
49 | 45 | return h('Page -threadNew', {title: strings.threadNew.pageTitle}, [ |
50 | 46 | api.app.html.sideNav(location), |
51 | 47 | h('div.content', [ |
52 | 48 | h('div.container', [ |
53 | 49 | h('div.field -to', [ |
54 | 50 | h('div.label', strings.threadNew.field.to), |
55 | 51 | h('div.recps', [ |
56 | 52 | map(meta.recps, Recipient), |
57 | | - h('input', { |
58 | | - 'ev-input': e => searchInput.set(e.target.value), |
59 | | - placeholder: strings.optionalField |
60 | | - }), |
| 53 | + RecipientInput(meta.recps) |
61 | 54 | ]) |
62 | 55 | ]), |
63 | 56 | h('div.field -subject', [ |
64 | 57 | h('div.label', strings.threadNew.field.subject), |
66 | 59 | 'ev-input': e => meta.subject.set(e.target.value), |
67 | 60 | placeholder: strings.optionalField |
68 | 61 | }), |
69 | 62 | ]), |
70 | | - composer |
| 63 | + Composer(meta) |
71 | 64 | ]) |
72 | 65 | ]) |
73 | 66 | ]) |
74 | 67 | |
79 | 72 | api.about.html.avatar(r.link, 'tiny'), |
80 | 73 | h('div.name', r.name) |
81 | 74 | ]) |
82 | 75 | } |
| 76 | + |
| 77 | + function RecipientInput (recps) { |
| 78 | + const getRecpSuggestions = api.about.async.suggest() |
| 79 | + const input = h('input', { |
| 80 | + placeholder: strings.threadNew.action.addMoreRecps |
| 81 | + |
| 82 | + }) |
| 83 | + |
| 84 | + var boxActive = false |
| 85 | + addSuggest() |
| 86 | + |
| 87 | + input.addEventListener('suggestselect', (e) => { |
| 88 | + const { id, title: name } = e.detail |
| 89 | + if (!recps.find(r => r === id || r.link === id)) |
| 90 | + recps.push({ link: id, name }) |
| 91 | + |
| 92 | + boxActive = false |
| 93 | + e.target.value = '' |
| 94 | + e.target.placeholder = '' |
| 95 | + }) |
| 96 | + |
| 97 | + input.addEventListener('keyup', (e) => { |
| 98 | + |
| 99 | + if (boxActive) { |
| 100 | + |
| 101 | + |
| 102 | + if (e.target.value === '') boxActive = false |
| 103 | + return |
| 104 | + } |
| 105 | + |
| 106 | + if (e.code === 'Backspace' || e.key === 'Backspace' || e.keyCode == 8) { |
| 107 | + if (recps.getLength() < 3) return |
| 108 | + |
| 109 | + recps.pop() |
| 110 | + } |
| 111 | + }) |
| 112 | + |
| 113 | + return input |
| 114 | + |
| 115 | + function addSuggest () { |
| 116 | + if (!input.parentElement) return setTimeout(addSuggest, 100) |
| 117 | + |
| 118 | + suggestBox(input, (inputText, cb) => { |
| 119 | + if (recps.getLength() >= 7) return |
| 120 | + |
| 121 | + |
| 122 | + boxActive = true |
| 123 | + const suggestions = getRecpSuggestions(inputText) |
| 124 | + cb(null, suggestions) |
| 125 | + }, {cls: 'PatchSuggest'}) |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + function Composer (meta) { |
| 130 | + return api.message.html.compose( |
| 131 | + { meta, shrink: false }, |
| 132 | + (err, msg) => { |
| 133 | + if (err) return api.history.sync.push(err) |
| 134 | + |
| 135 | + const someRecipient = meta.recps.get(1) |
| 136 | + if (!someRecipient) return |
| 137 | + |
| 138 | + api.history.sync.push(Object.assign( |
| 139 | + api.message.sync.unbox(msg), |
| 140 | + { feed: someRecipient.link } |
| 141 | + )) |
| 142 | + } |
| 143 | + ) |
| 144 | + } |
83 | 145 | } |
84 | 146 | |
85 | 147 | } |
86 | 148 | |