Files: e2fb4d766af3a45d510a0558e410b04dd3366e13 / app / page / threadNew.js
4139 bytesRaw
1 | const nest = require('depnest') |
2 | const { h, Struct, Value, Array: MutantArray, computed, map, resolve } = require('mutant') |
3 | const suggestBox = require('suggest-box') |
4 | |
5 | exports.gives = nest('app.page.threadNew') |
6 | |
7 | exports.needs = nest({ |
8 | 'about.async.suggest': 'first', |
9 | 'about.html.avatar': 'first', |
10 | 'about.obs.name': 'first', |
11 | 'app.html.sideNav': 'first', |
12 | 'app.html.thread': 'first', |
13 | 'history.sync.push': 'first', |
14 | 'keys.sync.id': 'first', |
15 | 'message.html.compose': 'first', |
16 | 'message.sync.unbox': 'first', |
17 | 'translations.sync.strings': 'first', |
18 | }) |
19 | |
20 | exports.create = (api) => { |
21 | |
22 | return nest('app.page.threadNew', threadNew) |
23 | |
24 | function threadNew (location) { |
25 | const { feed, channel } = location |
26 | |
27 | if (feed) return threadNewFeed(location) |
28 | } |
29 | |
30 | function threadNewFeed (location) { |
31 | const strings = api.translations.sync.strings() |
32 | const myId = api.keys.sync.id() |
33 | |
34 | const { feed } = location |
35 | |
36 | const meta = Struct({ |
37 | type: 'post', |
38 | recps: MutantArray ([ |
39 | myId, |
40 | { link: feed, name: resolve(api.about.obs.name(feed)) } |
41 | ]), |
42 | subject: Value() |
43 | }) |
44 | |
45 | return h('Page -threadNew', {title: strings.threadNew.pageTitle}, [ |
46 | api.app.html.sideNav(location), |
47 | h('div.content', [ |
48 | h('div.container', [ |
49 | h('div.field -to', [ |
50 | h('div.label', strings.threadNew.field.to), |
51 | h('div.recps', [ |
52 | map(meta.recps, Recipient), |
53 | RecipientInput(meta.recps) |
54 | ]) |
55 | ]), |
56 | h('div.field -subject', [ |
57 | h('div.label', strings.threadNew.field.subject), |
58 | h('input', { |
59 | 'ev-input': e => meta.subject.set(e.target.value), |
60 | placeholder: strings.optionalField |
61 | }), |
62 | ]), |
63 | Composer(meta) |
64 | ]) |
65 | ]) |
66 | ]) |
67 | |
68 | function Recipient (r) { |
69 | if (r === myId) return |
70 | |
71 | return h('div.recp', [ |
72 | api.about.html.avatar(r.link, 'tiny'), |
73 | h('div.name', r.name) |
74 | ]) |
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 | // 'ev-input': e => searchInput.set(e.target.value), |
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 | // don't pop the previous entry if still entering a name! |
99 | if (boxActive) { |
100 | // if you delete a name you were typing completely, mark box inactive |
101 | // so that further deletes pop names |
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 // can only delete down to 2 recps (sender + 1 recp) |
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 | // TODO - tell the user they're only allowed 6 (or 7?!) people in a message |
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), // for consistency of message sideNav receives D: |
140 | { feed: someRecipient.link } |
141 | )) |
142 | } |
143 | ) |
144 | } |
145 | } |
146 | |
147 | } |
148 | |
149 |
Built with git-ssb-web